diff options
author | Enrico Granata <granata.enrico@gmail.com> | 2011-07-29 19:53:35 +0000 |
---|---|---|
committer | Enrico Granata <granata.enrico@gmail.com> | 2011-07-29 19:53:35 +0000 |
commit | 6f3533fb1d742620328b4fcc79410d3e09d6eb8d (patch) | |
tree | 4ed75acf7c94fefcab457f17a568827d5b0e3c22 | |
parent | ce0ceebb1c5f896e992e1cac36fad732daf55cb0 (diff) | |
download | bcm5719-llvm-6f3533fb1d742620328b4fcc79410d3e09d6eb8d.tar.gz bcm5719-llvm-6f3533fb1d742620328b4fcc79410d3e09d6eb8d.zip |
Public API changes:
- Completely new implementation of SBType
- Various enhancements in several other classes
Python synthetic children providers for std::vector<T>, std::list<T> and std::map<K,V>:
- these return the actual elements into the container as the children of the container
- basic template name parsing that works (hopefully) on both Clang and GCC
- find them in examples/synthetic and in the test suite in functionalities/data-formatter/data-formatter-python-synth
New summary string token ${svar :
- the syntax is just the same as in ${var but this new token lets you read the values
coming from the synthetic children provider instead of the actual children
- Python providers above provide a synthetic child len that returns the number of elements
into the container
Full bug fix for the issue in which getting byte size for a non-complete type would crash LLDB
Several other fixes, including:
- inverted the order of arguments in the ClangASTType constructor
- EvaluationPoint now only returns SharedPointer's to Target and Process
- the help text for several type subcommands now correctly indicates argument-less options as such
llvm-svn: 136504
53 files changed, 2263 insertions, 586 deletions
diff --git a/lldb/examples/synthetic/StdListSynthProvider.py b/lldb/examples/synthetic/StdListSynthProvider.py new file mode 100644 index 00000000000..0f6ca4d5dd6 --- /dev/null +++ b/lldb/examples/synthetic/StdListSynthProvider.py @@ -0,0 +1,61 @@ +import re +class StdListSynthProvider: + def __init__(self, valobj, dict): + self.valobj = valobj; + self.update() + def num_children(self): + next_val = int(self.Mnext.GetValue(),0) + prev_val = int(self.Mprev.GetValue(),0) + if next_val == 0: + return 0; + if next_val == self.Mnode_address: + return 0; + if next_val == prev_val: + return 1; + size = 2 + current = self.Mnext + while int(current.GetChildMemberWithName('_M_next').GetValue(),0) != self.Mnode_address: + size = size + 1; + current = current.GetChildMemberWithName('_M_next') + return (size - 1) + def get_child_index(self,name): + if name == "len": + return self.num_children(); + else: + return int(name.lstrip('[').rstrip(']')) + def get_child_at_index(self,index): + if index == self.num_children(): + return self.valobj.CreateValueFromExpression("len",str(self.num_children())) + else: + offset = index + current = self.Mnext; + while offset > 0: + current = current.GetChildMemberWithName('_M_next'); + offset = offset - 1; + return current.CreateChildAtOffset('['+str(index)+']',2*current.GetType().GetByteSize(),self.data_type) + def extract_type_name(self,name): + self.type_name = name[16:] + index = 2 + count_of_template = 1 + while index < len(self.type_name): + if self.type_name[index] == '<': + count_of_template = count_of_template + 1; + elif self.type_name[index] == '>': + count_of_template = count_of_template - 1; + elif self.type_name[index] == ',' and count_of_template == 1: + self.type_name = self.type_name[:index] + break + index = index + 1; + self.type_name_nospaces = self.type_name.replace(", ", ",") + def update(self): + self.Mimpl = self.valobj.GetChildMemberWithName('_M_impl') + self.Mnode = self.Mimpl.GetChildMemberWithName('_M_node') + self.extract_type_name(self.Mimpl.GetType().GetName()) + self.Mnode_address = int(self.valobj.AddressOf().GetValue(), 0) + self.Mnext = self.Mnode.GetChildMemberWithName('_M_next') + self.Mprev = self.Mnode.GetChildMemberWithName('_M_prev') + self.data_type = self.Mnode.GetTarget().FindFirstType(self.type_name) + # tries to fight against a difference in formatting type names between gcc and clang + if self.data_type.IsValid() == False: + self.data_type = self.Mnode.GetTarget().FindFirstType(self.type_name_nospaces) + self.data_size = self.data_type.GetByteSize() diff --git a/lldb/examples/synthetic/StdMapSynthProvider.py b/lldb/examples/synthetic/StdMapSynthProvider.py new file mode 100644 index 00000000000..0665889896e --- /dev/null +++ b/lldb/examples/synthetic/StdMapSynthProvider.py @@ -0,0 +1,103 @@ +import re +class StdMapSynthProvider: + def __init__(self, valobj, dict): + self.valobj = valobj; + self.update() + def update(self): + self.Mt = self.valobj.GetChildMemberWithName('_M_t') + self.Mimpl = self.Mt.GetChildMemberWithName('_M_impl') + self.Mheader = self.Mimpl.GetChildMemberWithName('_M_header') + # from libstdc++ implementation of _M_root for rbtree + self.Mroot = self.Mheader.GetChildMemberWithName('_M_parent') + # the stuff into the tree is actually a std::pair<const key, value> + # life would be much easier if gcc had a coherent way to print out + # template names in debug info + self.expand_clang_type_name() + self.expand_gcc_type_name() + self.data_type = self.Mt.GetTarget().FindFirstType(self.clang_type_name) + if self.data_type.IsValid() == False: + self.data_type = self.Mt.GetTarget().FindFirstType(self.gcc_type_name) + self.data_size = self.data_type.GetByteSize() + self.skip_size = self.Mheader.GetType().GetByteSize() + def expand_clang_type_name(self): + type_name = self.Mimpl.GetType().GetName() + index = type_name.find("std::pair<") + type_name = type_name[index+5:] + index = 6 + template_count = 1 + while index < len(type_name): + if type_name[index] == '<': + template_count = template_count + 1 + elif type_name[index] == '>' and template_count == 1: + type_name = type_name[:index+1] + break + elif type_name[index] == '>': + template_count = template_count - 1 + index = index + 1; + self.clang_type_name = type_name + def expand_gcc_type_name(self): + type_name = self.Mt.GetType().GetName() + index = type_name.find("std::pair<") + type_name = type_name[index+5:] + index = 6 + template_count = 1 + while index < len(type_name): + if type_name[index] == '<': + template_count = template_count + 1 + elif type_name[index] == '>' and template_count == 1: + type_name = type_name[:index+1] + break + elif type_name[index] == '>': + template_count = template_count - 1 + elif type_name[index] == ' ' and template_count == 1 and type_name[index-1] == ',': + type_name = type_name[0:index] + type_name[index+1:] + index = index - 1 + index = index + 1; + self.gcc_type_name = type_name + def num_children(self): + root_ptr_val = self.node_ptr_value(self.Mroot) + if root_ptr_val == 0: + return 0; + return int(self.Mimpl.GetChildMemberWithName('_M_node_count').GetValue(), 0); + def get_child_index(self,name): + if name == "len": + return self.num_children(); + else: + return int(name.lstrip('[').rstrip(']')) + def get_child_at_index(self,index): + if index == self.num_children(): + return self.valobj.CreateValueFromExpression("len",str(self.num_children())) + else: + offset = index + current = self.left(self.Mheader); + while offset > 0: + current = self.increment_node(current) + offset = offset - 1; + # skip all the base stuff and get at the data + return current.CreateChildAtOffset('['+str(index)+']',self.skip_size,self.data_type) + # utility functions + def node_ptr_value(self,node): + return int(node.GetValue(),0); + def right(self,node): + return node.GetChildMemberWithName("_M_right"); + def left(self,node): + return node.GetChildMemberWithName("_M_left"); + def parent(self,node): + return node.GetChildMemberWithName("_M_parent"); + # from libstdc++ implementation of iterator for rbtree + def increment_node(self,node): + if self.node_ptr_value(self.right(node)) != 0: + x = self.right(node); + while self.node_ptr_value(self.left(x)) != 0: + x = self.left(x); + return x; + else: + x = node; + y = self.parent(x) + while(self.node_ptr_value(x) == self.node_ptr_value(self.right(y))): + x = y; + y = self.parent(y); + if self.node_ptr_value(self.right(x)) != self.node_ptr_value(y): + x = y; + return x; + diff --git a/lldb/examples/synthetic/StdVectorSynthProvider.py b/lldb/examples/synthetic/StdVectorSynthProvider.py new file mode 100644 index 00000000000..91e634a718a --- /dev/null +++ b/lldb/examples/synthetic/StdVectorSynthProvider.py @@ -0,0 +1,25 @@ +class StdVectorSynthProvider: + def __init__(self, valobj, dict): + self.valobj = valobj; + self.update() + def num_children(self): + start_val = int(self.Mstart.GetValue(),0) + finish_val = int(self.Mfinish.GetValue(),0) + return (finish_val-start_val)/self.data_size + def get_child_index(self,name): + if name == "len": + return self.num_children(); + else: + return int(name.lstrip('[').rstrip(']')) + def get_child_at_index(self,index): + if index == self.num_children(): + return self.valobj.CreateValueFromExpression("len",str(self.num_children())) + else: + offset = index * self.data_size + return self.Mstart.CreateChildAtOffset('['+str(index)+']',offset,self.data_type) + def update(self): + self.Mimpl = self.valobj.GetChildMemberWithName('_M_impl') + self.Mstart = self.Mimpl.GetChildMemberWithName('_M_start') + self.Mfinish = self.Mimpl.GetChildMemberWithName('_M_finish') + self.data_type = self.Mstart.GetType().GetPointeeType() + self.data_size = self.data_type.GetByteSize() diff --git a/lldb/include/lldb/API/SBDefines.h b/lldb/include/lldb/API/SBDefines.h index 8f603719a13..72e6785ed58 100644 --- a/lldb/include/lldb/API/SBDefines.h +++ b/lldb/include/lldb/API/SBDefines.h @@ -56,6 +56,8 @@ class SBSymbolContext; class SBSymbolContextList; class SBTarget; class SBThread; +class SBType; +class SBTypeList; class SBValue; class SBValueList; diff --git a/lldb/include/lldb/API/SBModule.h b/lldb/include/lldb/API/SBModule.h index a762dbf89c1..ba4f4e94c76 100644 --- a/lldb/include/lldb/API/SBModule.h +++ b/lldb/include/lldb/API/SBModule.h @@ -153,6 +153,11 @@ public: const char *name, uint32_t max_matches); + lldb::SBType + FindFirstType (const char* name); + + lldb::SBTypeList + FindTypes (const char* type); private: friend class SBAddress; diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h index 574211595e3..bb0f9717513 100644 --- a/lldb/include/lldb/API/SBTarget.h +++ b/lldb/include/lldb/API/SBTarget.h @@ -14,6 +14,7 @@ #include "lldb/API/SBAddress.h" #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBType.h" namespace lldb { @@ -342,6 +343,12 @@ public: lldb::SBBroadcaster GetBroadcaster () const; + + lldb::SBType + FindFirstType (const char* type); + + lldb::SBTypeList + FindTypes (const char* type); #ifndef SWIG bool @@ -367,6 +374,7 @@ protected: friend class SBProcess; friend class SBSymbol; friend class SBModule; + friend class SBValue; //------------------------------------------------------------------ // Constructors are private, use static Target::Create function to diff --git a/lldb/include/lldb/API/SBType.h b/lldb/include/lldb/API/SBType.h index 03928fe39e0..8142b9b0337 100644 --- a/lldb/include/lldb/API/SBType.h +++ b/lldb/include/lldb/API/SBType.h @@ -11,128 +11,109 @@ #define LLDB_SBType_h_ #include "lldb/API/SBDefines.h" +#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/Type.h" namespace lldb { -class SBTypeMember; +class SBTypeList; class SBType { public: - SBType (void *ast = NULL, void *clang_type = NULL); - SBType (const SBType &rhs); ~SBType (); #ifndef SWIG - const SBType & - operator =(const SBType &rhs); -#endif - - bool - IsValid(); - - const char * - GetName(); - - uint64_t - GetByteSize(); - -#ifndef SWIG - lldb::Encoding - GetEncoding (uint32_t &count); -#endif - - uint64_t - GetNumberChildren (bool omit_empty_base_classes); - - bool - GetChildAtIndex (bool omit_empty_base_classes, uint32_t idx, SBTypeMember &member); - - uint32_t - GetChildIndexForName (bool omit_empty_base_classes, const char *name); - + const lldb::SBType & + operator = (const lldb::SBType &rhs); + bool - IsAPointerType (); - - SBType - GetPointeeType (); - - static bool - IsPointerType (void *opaque_type); - + operator == (const lldb::SBType &rhs) const; + bool - GetDescription (lldb::SBStream &description); - -protected: - void *m_ast; - void *m_type; -}; - -class SBTypeMember -{ -public: - - SBTypeMember (); + operator != (const lldb::SBType &rhs) const; + + lldb_private::TypeImpl & + ref (); + + const lldb_private::TypeImpl & + ref () const; - SBTypeMember (const SBTypeMember &rhs); - -#ifndef SWIG - const SBTypeMember& - operator =(const SBTypeMember &rhs); #endif - - ~SBTypeMember (); - + bool - IsBaseClass (); + IsValid() const; + + size_t + GetByteSize() const; bool - IsValid (); - - void - Clear(); - + IsPointerType() const; + bool - IsBitfield (); + IsReferenceType() const; - size_t - GetBitfieldWidth (); + SBType + GetPointerType() const; - size_t - GetBitfieldOffset (); - - size_t - GetOffset (); - - const char * - GetName (); - SBType - GetType(); - + GetPointeeType() const; + SBType - GetParentType(); - - void - SetName (const char *name); - + GetReferenceType() const; + + SBType + GetDereferencedType() const; + + SBType + GetBasicType(lldb::BasicType type) const; + + const char* + GetName(); + protected: - friend class SBType; + std::auto_ptr<lldb_private::TypeImpl> m_opaque_ap; + + friend class SBModule; + friend class SBTarget; + friend class SBValue; + friend class SBTypeList; - void *m_ast; - void *m_parent_type; - void *m_member_type; - char *m_member_name; - int32_t m_offset; - uint32_t m_bit_size; - uint32_t m_bit_offset; - bool m_is_base_class; - bool m_is_deref_of_paremt; + SBType (clang::ASTContext*, clang_type_t); + SBType (lldb_private::ClangASTType type); + SBType (lldb::TypeSP type); + SBType (lldb_private::TypeImpl impl); + SBType(); + +}; + +class SBTypeList +{ +public: + SBTypeList(); + + SBTypeList(const SBTypeList& rhs); + + SBTypeList& + operator = (const SBTypeList& rhs); + + void + AppendType(SBType type); + + SBType + GetTypeAtIndex(int index) const; + + int + GetSize() const; + + ~SBTypeList(); + +private: + std::auto_ptr<lldb_private::TypeListImpl> m_opaque_ap; }; - } // namespace lldb diff --git a/lldb/include/lldb/API/SBValue.h b/lldb/include/lldb/API/SBValue.h index 6170bdf4780..a145aef0ccc 100644 --- a/lldb/include/lldb/API/SBValue.h +++ b/lldb/include/lldb/API/SBValue.h @@ -11,6 +11,7 @@ #define LLDB_SBValue_h_ #include "lldb/API/SBDefines.h" +#include "lldb/API/SBType.h" #include <stdio.h> @@ -105,6 +106,18 @@ public: lldb::SBValue GetChildAtIndex (uint32_t idx); + + lldb::SBValue + CreateChildAtOffset (const char *name, uint32_t offset, const SBType& type); + + lldb::SBValue + Cast(const SBType& type); + + lldb::SBValue + CreateValueFromExpression (const char *name, const char* expression); + + lldb::SBValue + CreateValueFromAddress(const char* name, lldb::addr_t address, const SBType& type); //------------------------------------------------------------------ /// Get a child value by index from a value. @@ -179,6 +192,9 @@ public: // Expands nested expressions like .a->b[0].c[1]->d lldb::SBValue GetValueForExpressionPath(const char* expr_path); + + lldb::SBValue + AddressOf(); uint32_t GetNumChildren (); @@ -186,12 +202,26 @@ public: void * GetOpaqueType(); + lldb::SBTarget + GetTarget(); + + lldb::SBProcess + GetProcess(); + + lldb::SBThread + GetThread(); + lldb::SBFrame + GetFrame(); + lldb::SBValue Dereference (); bool TypeIsPointerType (); + + SBType + GetType(); bool GetDescription (lldb::SBStream &description); diff --git a/lldb/include/lldb/Core/FormatClasses.h b/lldb/include/lldb/Core/FormatClasses.h index c18f64b62ac..0d11062a8cc 100644 --- a/lldb/include/lldb/Core/FormatClasses.h +++ b/lldb/include/lldb/Core/FormatClasses.h @@ -113,6 +113,9 @@ public: virtual uint32_t GetIndexOfChildWithName (const ConstString &name) = 0; + virtual void + Update() = 0; + typedef lldb::SharedPtr<SyntheticChildrenFrontEnd>::Type SharedPointer; }; @@ -238,6 +241,9 @@ public: return m_backend->GetSyntheticExpressionPathChild(filter->GetExpressionPathAtIndex(idx).c_str(), can_create); } + virtual void + Update() {} + virtual uint32_t GetIndexOfChildWithName (const ConstString &name) { @@ -328,6 +334,15 @@ public: return sb_ptr->m_opaque_sp; } + + virtual void + Update() + { + if (m_wrapper == NULL || m_interpreter == NULL) + return; + + m_interpreter->UpdateSynthProviderInstance(m_wrapper); + } virtual uint32_t GetIndexOfChildWithName (const ConstString &name) diff --git a/lldb/include/lldb/Core/FormatManager.h b/lldb/include/lldb/Core/FormatManager.h index b5d1a39560d..c8a2fdddcad 100644 --- a/lldb/include/lldb/Core/FormatManager.h +++ b/lldb/include/lldb/Core/FormatManager.h @@ -225,7 +225,7 @@ public: MapValueType& entry, uint32_t* why = NULL) { - uint32_t value = lldb::eFormatterDirectChoice; + uint32_t value = lldb::eFormatterChoiceCriterionDirectChoice; clang::QualType type = clang::QualType::getFromOpaquePtr(vobj.GetClangType()); bool ret = Get(vobj, type, entry, value); if (ret) @@ -315,7 +315,7 @@ private: log->Printf("stripping reference"); if (Get(vobj,type.getNonReferenceType(),entry, reason) && !entry->m_skip_references) { - reason |= lldb::eFormatterStrippedPointerReference; + reason |= lldb::eFormatterChoiceCriterionStrippedPointerReference; return true; } } @@ -325,7 +325,7 @@ private: log->Printf("stripping pointer"); if (Get(vobj, typePtr->getPointeeType(), entry, reason) && !entry->m_skip_pointers) { - reason |= lldb::eFormatterStrippedPointerReference; + reason |= lldb::eFormatterChoiceCriterionStrippedPointerReference; return true; } } @@ -345,7 +345,7 @@ private: return false; if (Get(*target, typePtr->getPointeeType(), entry, reason) && !entry->m_skip_pointers) { - reason |= lldb::eFormatterStrippedPointerReference; + reason |= lldb::eFormatterChoiceCriterionStrippedPointerReference; return true; } } @@ -370,7 +370,7 @@ private: clang::QualType ivar_qual_type(ast->getObjCInterfaceType(superclass_interface_decl)); if (Get(vobj, ivar_qual_type, entry, reason) && entry->m_cascades) { - reason |= lldb::eFormatterNavigatedBaseClasses; + reason |= lldb::eFormatterChoiceCriterionNavigatedBaseClasses; return true; } } @@ -399,7 +399,7 @@ private: { if ((Get(vobj, pos->getType(), entry, reason)) && entry->m_cascades) { - reason |= lldb::eFormatterNavigatedBaseClasses; + reason |= lldb::eFormatterChoiceCriterionNavigatedBaseClasses; return true; } } @@ -413,7 +413,7 @@ private: { if ((Get(vobj, pos->getType(), entry, reason)) && entry->m_cascades) { - reason |= lldb::eFormatterNavigatedBaseClasses; + reason |= lldb::eFormatterChoiceCriterionNavigatedBaseClasses; return true; } } @@ -429,7 +429,7 @@ private: log->Printf("stripping typedef"); if ((Get(vobj, type_tdef->getDecl()->getUnderlyingType(), entry, reason)) && entry->m_cascades) { - reason |= lldb::eFormatterNavigatedTypedefs; + reason |= lldb::eFormatterChoiceCriterionNavigatedTypedefs; return true; } } @@ -539,7 +539,7 @@ public: return true; bool regex = RegexSummary()->Get(vobj, entry, reason); if (regex && reason) - *reason |= lldb::eFormatterRegularExpressionSummary; + *reason |= lldb::eFormatterChoiceCriterionRegularExpressionSummary; return regex; } @@ -775,7 +775,7 @@ public: lldb::SummaryFormatSP current_format; if (!category->Get(vobj, current_format, &reason_why)) continue; - if (reason_why == lldb::eFormatterDirectChoice) + if (reason_why == lldb::eFormatterChoiceCriterionDirectChoice) { entry = current_format; return true; @@ -806,7 +806,7 @@ public: lldb::SyntheticChildrenSP current_format; if (!category->Get(vobj, current_format, &reason_why)) continue; - if (reason_why == lldb::eFormatterDirectChoice) + if (reason_why == lldb::eFormatterChoiceCriterionDirectChoice) { entry = current_format; return true; diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h index 0a1cb743841..c0925f0d903 100644 --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -686,6 +686,15 @@ protected: SetArchitecture (const ArchSpec &new_arch); private: + + uint32_t + FindTypes_Impl (const SymbolContext& sc, + const ConstString &name, + bool append, + uint32_t max_matches, + TypeList& types); + + DISALLOW_COPY_AND_ASSIGN (Module); }; diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h index e60366a39e2..65732529ac8 100644 --- a/lldb/include/lldb/Core/ModuleList.h +++ b/lldb/include/lldb/Core/ModuleList.h @@ -440,6 +440,13 @@ protected: collection m_modules; ///< The collection of modules. mutable Mutex m_modules_mutex; +private: + uint32_t + FindTypes_Impl (const SymbolContext& sc, + const ConstString &name, + bool append, + uint32_t max_matches, + TypeList& types); }; } // namespace lldb_private diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h index 2fb7b406938..da75b46be15 100644 --- a/lldb/include/lldb/Core/ValueObject.h +++ b/lldb/include/lldb/Core/ValueObject.h @@ -197,17 +197,17 @@ public: ExecutionContextScope * GetExecutionContextScope (); - - Target * - GetTarget () const + + lldb::TargetSP + GetTargetSP () const { - return m_target_sp.get(); + return m_target_sp; } - Process * - GetProcess () const + lldb::ProcessSP + GetProcessSP () const { - return m_process_sp.get(); + return m_process_sp; } // Set the EvaluationPoint to the values in exe_scope, @@ -548,6 +548,9 @@ public: 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); @@ -755,7 +758,8 @@ protected: 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_expression_path_child:1, + m_is_child_at_offset:1; // used to prevent endless looping into GetpPrintableRepresentation() uint32_t m_dump_printable_counter; @@ -806,12 +810,6 @@ protected: CalculateNumChildren() = 0; void - SetName (const char *name); - - void - SetName (const ConstString &name); - - void SetNumChildren (uint32_t num_children); void @@ -824,6 +822,10 @@ protected: ClearUserVisibleData(); public: + + void + SetName (const ConstString &name); + lldb::addr_t GetPointerValue (AddressType &address_type, bool scalar_is_load_address); diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h index 484062bfb68..2fb4273bdae 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -38,10 +38,11 @@ public: const char *session_dictionary_name, const lldb::ValueObjectSP& valobj_sp); - typedef uint32_t (*SWIGPythonCalculateNumChildren) (void *implementor); - typedef void* (*SWIGPythonGetChildAtIndex) (void *implementor, uint32_t idx); - typedef int (*SWIGPythonGetIndexOfChildWithName) (void *implementor, const char* child_name); - typedef lldb::SBValue* (*SWIGPythonCastPyObjectToSBValue) (void* data); + typedef uint32_t (*SWIGPythonCalculateNumChildren) (void *implementor); + typedef void* (*SWIGPythonGetChildAtIndex) (void *implementor, uint32_t idx); + typedef int (*SWIGPythonGetIndexOfChildWithName) (void *implementor, const char* child_name); + typedef lldb::SBValue* (*SWIGPythonCastPyObjectToSBValue) (void* data); + typedef void (*SWIGPythonUpdateSynthProviderInstance) (void* data); typedef enum { @@ -157,6 +158,11 @@ public: return UINT32_MAX; } + virtual void + UpdateSynthProviderInstance (void* implementor) + { + } + virtual lldb::SBValue* CastPyObjectToSBValue (void* data) { @@ -183,7 +189,8 @@ public: SWIGPythonCalculateNumChildren python_swig_calc_children, SWIGPythonGetChildAtIndex python_swig_get_child_index, SWIGPythonGetIndexOfChildWithName python_swig_get_index_child, - SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue); + SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue, + SWIGPythonUpdateSynthProviderInstance python_swig_update_provider); static void TerminateInterpreter (); diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h index 563a7d3bc02..068095c9c66 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h @@ -72,6 +72,9 @@ public: virtual int GetIndexOfChildWithName (void *implementor, const char* child_name); + virtual void + UpdateSynthProviderInstance (void* implementor); + virtual lldb::SBValue* CastPyObjectToSBValue (void* data); @@ -127,7 +130,8 @@ public: SWIGPythonCalculateNumChildren python_swig_calc_children, SWIGPythonGetChildAtIndex python_swig_get_child_index, SWIGPythonGetIndexOfChildWithName python_swig_get_index_child, - SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalu); + SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue, + SWIGPythonUpdateSynthProviderInstance python_swig_update_provider); protected: diff --git a/lldb/include/lldb/Symbol/ClangASTType.h b/lldb/include/lldb/Symbol/ClangASTType.h index 9aa78fd713a..9692e32f693 100644 --- a/lldb/include/lldb/Symbol/ClangASTType.h +++ b/lldb/include/lldb/Symbol/ClangASTType.h @@ -29,9 +29,10 @@ namespace lldb_private { class ClangASTType { public: - ClangASTType (lldb::clang_type_t type, clang::ASTContext *ast_context) : - m_type (type), - m_ast (ast_context) + + ClangASTType (clang::ASTContext *ast_context, lldb::clang_type_t type) : + m_type (type), + m_ast (ast_context) { } @@ -188,7 +189,7 @@ public: GetFormat (lldb::clang_type_t opaque_clang_qual_type); uint32_t - GetTypeByteSize(); + GetTypeByteSize() const; static uint32_t GetTypeByteSize(clang::ASTContext *ast_context, diff --git a/lldb/include/lldb/Symbol/TaggedASTType.h b/lldb/include/lldb/Symbol/TaggedASTType.h index 697f7777fe3..fbd18972281 100644 --- a/lldb/include/lldb/Symbol/TaggedASTType.h +++ b/lldb/include/lldb/Symbol/TaggedASTType.h @@ -21,7 +21,7 @@ template <unsigned int C> class TaggedASTType : public ClangASTType { public: TaggedASTType (lldb::clang_type_t type, clang::ASTContext *ast_context) : - ClangASTType(type, ast_context) { } + ClangASTType(ast_context, type) { } TaggedASTType (const TaggedASTType<C> &tw) : ClangASTType(tw) { } diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h index 7dac894318a..0868d4626b7 100644 --- a/lldb/include/lldb/Symbol/Type.h +++ b/lldb/include/lldb/Symbol/Type.h @@ -18,7 +18,7 @@ #include <set> namespace lldb_private { - + class Type : public UserID { public: @@ -293,6 +293,99 @@ private: ConstString m_type_name; }; +// the two classes here are used by the public API as a backend to +// the SBType and SBTypeList classes + +class TypeImpl +{ +private: + std::auto_ptr<ClangASTType> m_clang_ast_type; + lldb::TypeSP m_lldb_type; + +public: + + TypeImpl() : + m_clang_ast_type(NULL), + m_lldb_type(lldb::TypeSP()) + {} + + TypeImpl(const TypeImpl& rhs) : + m_clang_ast_type(rhs.m_clang_ast_type.get()), + m_lldb_type(rhs.m_lldb_type) + {} + + TypeImpl& + operator = (const TypeImpl& rhs); + + bool + operator == (const TypeImpl& rhs) + { + return (m_clang_ast_type.get() == rhs.m_clang_ast_type.get()) && + (m_lldb_type.get() == rhs.m_lldb_type.get()); + } + + bool + operator != (const TypeImpl& rhs) + { + return (m_clang_ast_type.get() != rhs.m_clang_ast_type.get()) || + (m_lldb_type.get() != rhs.m_lldb_type.get()); + } + + TypeImpl(const lldb_private::ClangASTType& type); + + TypeImpl(lldb::TypeSP type); + + bool + IsValid() + { + return (m_lldb_type.get() != NULL) || (m_clang_ast_type.get() != NULL); + } + + lldb_private::ClangASTType* + GetClangASTType() + { + return m_clang_ast_type.get(); + } + + clang::ASTContext* + GetASTContext(); + + lldb::clang_type_t + GetOpaqueQualType(); +}; + +class TypeListImpl +{ +public: + TypeListImpl() : + m_content() {} + + void + AppendType(TypeImpl& type) + { + m_content.push_back(type); + } + + TypeImpl + GetTypeAtIndex(int index) + { + if (index < 0 || index >= GetSize()) + return TypeImpl(); + + return m_content[index]; + } + + int + GetSize() + { + return m_content.size(); + } + +private: + std::vector<TypeImpl> m_content; +}; + + } // namespace lldb_private #endif // liblldb_Type_h_ diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index e7961c88c72..b9c504b3437 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -496,19 +496,52 @@ namespace lldb { eFunctionNameTypeSelector = (1u << 5) // Find function by selector name (ObjC) names } FunctionNameType; - // this enum determines how a FormatNavigator picked a specific format for a datatype - // these values can be used together (e.g. eFormatterStrippedPointerReference | eFormatterNavigatedBaseClasses - // if you went from DerivedType& to BaseType to find a valid format) + //---------------------------------------------------------------------- + // Ways that the FormatManager picks a particular format for a type + //---------------------------------------------------------------------- typedef enum FormatterChoiceCriterion { - eFormatterDirectChoice = 0x00000000, - eFormatterStrippedPointerReference = 0x00000001, - eFormatterNavigatedTypedefs = 0x00000002, - eFormatterNavigatedBaseClasses = 0x00000004, - eFormatterRegularExpressionSummary = 0x00000008 + eFormatterChoiceCriterionDirectChoice = 0x00000000, + eFormatterChoiceCriterionStrippedPointerReference = 0x00000001, + eFormatterChoiceCriterionNavigatedTypedefs = 0x00000002, + eFormatterChoiceCriterionNavigatedBaseClasses = 0x00000004, + eFormatterChoiceCriterionRegularExpressionSummary = 0x00000008 } FormatterChoiceCriterion; - + //---------------------------------------------------------------------- + // Basic types enumeration for the public API SBType::GetBasicType() + //---------------------------------------------------------------------- + typedef enum BasicType + { + eBasicTypeInvalid = 0, + eBasicTypeVoid = 1, + eBasicTypeChar, + eBasicTypeSignedChar, + eBasicTypeWChar, + eBasicTypeChar16, + eBasicTypeChar32, + eBasicTypeShort, + eBasicTypeUnsignedShort, + eBasicTypeInt, + eBasicTypeUnsignedInt, + eBasicTypeLong, + eBasicTypeUnsignedLong, + eBasicTypeLongLong, + eBasicTypeUnsignedLongLong, + eBasicTypeInt128, + eBasicTypeUnsignedInt128, + eBasicTypeBool, + eBasicTypeFloat, + eBasicTypeDouble, + eBasicTypeLongDouble, + eBasicTypeFloatComplex, + eBasicTypeDoubleComplex, + eBasicTypeLongDoubleComplex, + eBasicTypeObjCID, + eBasicTypeObjCClass, + eBasicTypeObjCSel + } BasicType; + } // namespace lldb diff --git a/lldb/scripts/Python/interface/SBModule.i b/lldb/scripts/Python/interface/SBModule.i index cea05e7ce9d..6f78dff68df 100644 --- a/lldb/scripts/Python/interface/SBModule.i +++ b/lldb/scripts/Python/interface/SBModule.i @@ -137,6 +137,13 @@ public: uint32_t name_type_mask, // Logical OR one or more FunctionNameType enum bits bool append, lldb::SBSymbolContextList& sc_list); + + lldb::SBType + FindFirstType (const char* name); + + lldb::SBTypeList + FindTypes (const char* type); + %feature("docstring", " //------------------------------------------------------------------ diff --git a/lldb/scripts/Python/interface/SBTarget.i b/lldb/scripts/Python/interface/SBTarget.i index 3ad6bed704a..40646209be5 100644 --- a/lldb/scripts/Python/interface/SBTarget.i +++ b/lldb/scripts/Python/interface/SBTarget.i @@ -320,6 +320,12 @@ public: uint32_t name_type_mask, // Logical OR one or more FunctionNameType enum bits bool append, lldb::SBSymbolContextList& sc_list); + + lldb::SBType + FindFirstType (const char* type); + + lldb::SBTypeList + FindTypes (const char* type); %feature("docstring", " //------------------------------------------------------------------ diff --git a/lldb/scripts/Python/interface/SBType.i b/lldb/scripts/Python/interface/SBType.i index e7d57b4fe76..03cfe44906d 100644 --- a/lldb/scripts/Python/interface/SBType.i +++ b/lldb/scripts/Python/interface/SBType.i @@ -9,91 +9,63 @@ namespace lldb { -class SBTypeMember; - -class SBType -{ -public: - - SBType (void *ast = NULL, void *clang_type = NULL); - - SBType (const SBType &rhs); - - ~SBType (); - - bool - IsValid(); - - const char * - GetName(); - - uint64_t - GetByteSize(); - - uint64_t - GetNumberChildren (bool omit_empty_base_classes); - - bool - GetChildAtIndex (bool omit_empty_base_classes, uint32_t idx, SBTypeMember &member); - - uint32_t - GetChildIndexForName (bool omit_empty_base_classes, const char *name); - - bool - IsAPointerType (); - - SBType - GetPointeeType (); - - static bool - IsPointerType (void *opaque_type); - - bool - GetDescription (lldb::SBStream &description); -}; - -class SBTypeMember -{ -public: - - SBTypeMember (); - - SBTypeMember (const SBTypeMember &rhs); - - ~SBTypeMember (); - - bool - IsBaseClass (); - - bool - IsValid (); - - void - Clear(); - - bool - IsBitfield (); - - size_t - GetBitfieldWidth (); + class SBType + { + public: + + SBType (const SBType &rhs); + + ~SBType (); + + bool + IsValid() const; + + size_t + GetByteSize() const; + + bool + IsPointerType() const; + + bool + IsReferenceType() const; + + SBType + GetPointerType() const; + + SBType + GetPointeeType() const; + + SBType + GetReferenceType() const; + + SBType + GetDereferencedType() const; + + SBType + GetBasicType(lldb::BasicType type) const; + + const char* + GetName(); + }; - size_t - GetBitfieldOffset (); - - size_t - GetOffset (); - - const char * - GetName (); - - SBType - GetType(); - - SBType - GetParentType(); - - void - SetName (const char *name); -}; + class SBTypeList + { + public: + SBTypeList(); + + void + AppendType(SBType type); + + SBType + GetTypeAtIndex(int index); + + int + GetSize(); + + ~SBTypeList(); + + private: + std::auto_ptr<SBTypeListImpl> m_content; + }; } // namespace lldb diff --git a/lldb/scripts/Python/interface/SBValue.i b/lldb/scripts/Python/interface/SBValue.i index 68e97e3323e..24f966099c3 100644 --- a/lldb/scripts/Python/interface/SBValue.i +++ b/lldb/scripts/Python/interface/SBValue.i @@ -203,7 +203,22 @@ public: GetChildAtIndex (uint32_t idx, lldb::DynamicValueType use_dynamic, bool can_create_synthetic); + + lldb::SBValue + CreateChildAtOffset (const char *name, uint32_t offset, const SBType& type); + + lldb::SBValue + SBValue::Cast(const SBType& type); + lldb::SBValue + CreateValueFromExpression (const char *name, const char* expression); + + lldb::SBValue + CreateValueFromAddress(const char* name, lldb::addr_t address, const SBType& type); + + lldb::SBType + GetType(); + %feature("docstring", " //------------------------------------------------------------------ /// Returns the child member index. @@ -257,13 +272,27 @@ public: void * GetOpaqueType(); - lldb::SBValue Dereference (); + lldb::SBValue + AddressOf(); + bool TypeIsPointerType (); + + lldb::SBTarget + GetTarget(); + lldb::SBProcess + GetProcess(); + + lldb::SBThread + GetThread(); + + lldb::SBFrame + GetFrame(); + bool GetDescription (lldb::SBStream &description); diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp index 1124d56e169..30fc171e0ed 100644 --- a/lldb/source/API/SBCommandInterpreter.cpp +++ b/lldb/source/API/SBCommandInterpreter.cpp @@ -331,10 +331,11 @@ LLDBSwigPythonCreateSyntheticProvider ); -extern "C" uint32_t LLDBSwigPython_CalculateNumChildren (void *implementor); -extern "C" void* LLDBSwigPython_GetChildAtIndex (void *implementor, uint32_t idx); -extern "C" int LLDBSwigPython_GetIndexOfChildWithName (void *implementor, const char* child_name); -extern "C" lldb::SBValue* LLDBSWIGPython_CastPyObjectToSBValue (void* data); +extern "C" uint32_t LLDBSwigPython_CalculateNumChildren (void *implementor); +extern "C" void* LLDBSwigPython_GetChildAtIndex (void *implementor, uint32_t idx); +extern "C" int LLDBSwigPython_GetIndexOfChildWithName (void *implementor, const char* child_name); +extern "C" lldb::SBValue* LLDBSWIGPython_CastPyObjectToSBValue (void* data); +extern "C" void LLDBSwigPython_UpdateSynthProviderInstance (void* implementor); extern "C" void init_lldb(void); @@ -352,6 +353,7 @@ SBCommandInterpreter::InitializeSWIG () LLDBSwigPython_CalculateNumChildren, LLDBSwigPython_GetChildAtIndex, LLDBSwigPython_GetIndexOfChildWithName, - LLDBSWIGPython_CastPyObjectToSBValue); + LLDBSWIGPython_CastPyObjectToSBValue, + LLDBSwigPython_UpdateSynthProviderInstance); } } diff --git a/lldb/source/API/SBModule.cpp b/lldb/source/API/SBModule.cpp index 852952af303..faeb5e9a50a 100644 --- a/lldb/source/API/SBModule.cpp +++ b/lldb/source/API/SBModule.cpp @@ -17,6 +17,7 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectList.h" #include "lldb/Core/ValueObjectVariable.h" +#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/Target.h" @@ -342,3 +343,59 @@ SBModule::FindGlobalVariables (SBTarget &target, const char *name, uint32_t max_ return sb_value_list; } + +lldb::SBType +SBModule::FindFirstType (const char* name_cstr) +{ + if (!IsValid()) + return lldb::SBType(); + + SymbolContext sc; + TypeList type_list; + uint32_t num_matches = 0; + ConstString name(name_cstr); + + num_matches = m_opaque_sp->FindTypes(sc, + name, + false, + 1, + type_list); + + if (num_matches) + { + TypeSP type_sp (type_list.GetTypeAtIndex(0)); + return lldb::SBType(type_sp); + } + else + return lldb::SBType(); +} + +lldb::SBTypeList +SBModule::FindTypes (const char* type) +{ + + SBTypeList retval; + + if (!IsValid()) + return retval; + + SymbolContext sc; + TypeList type_list; + uint32_t num_matches = 0; + ConstString name(type); + + num_matches = m_opaque_sp->FindTypes(sc, + name, + false, + UINT32_MAX, + type_list); + + for (size_t idx = 0; idx < num_matches; idx++) + { + TypeSP sp_at_idx = type_list.GetTypeAtIndex(idx); + + retval.AppendType(SBType(sp_at_idx)); + } + + return retval; +}
\ No newline at end of file diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index 22504402115..82da45a3225 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -38,6 +38,7 @@ #include "lldb/Host/FileSpec.h" #include "lldb/Host/Host.h" #include "lldb/Interpreter/Args.h" +#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -879,6 +880,52 @@ SBTarget::FindFunctions (const char *name, return 0; } +lldb::SBType +SBTarget::FindFirstType (const char* type) +{ + if (m_opaque_sp) + { + size_t count = m_opaque_sp->GetImages().GetSize(); + for (size_t idx = 0; idx < count; idx++) + { + SBType found_at_idx = GetModuleAtIndex(idx).FindFirstType(type); + + if (found_at_idx.IsValid()) + return found_at_idx; + } + } + return SBType(); +} + +lldb::SBTypeList +SBTarget::FindTypes (const char* type) +{ + + SBTypeList retval; + + if (m_opaque_sp) + { + ModuleList& images = m_opaque_sp->GetImages(); + ConstString name_const(type); + SymbolContext sc; + TypeList type_list; + + uint32_t num_matches = images.FindTypes(sc, + name_const, + true, + UINT32_MAX, + type_list); + + for (size_t idx = 0; idx < num_matches; idx++) + { + TypeSP sp_at_idx = type_list.GetTypeAtIndex(idx); + + retval.AppendType(SBType(sp_at_idx)); + } + } + return retval; +} + SBValueList SBTarget::FindGlobalVariables (const char *name, uint32_t max_matches) { diff --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp index 647a20c4327..b17dd8a1417 100644 --- a/lldb/source/API/SBType.cpp +++ b/lldb/source/API/SBType.cpp @@ -9,6 +9,12 @@ #include <string.h> +#include "clang/AST/ASTContext.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/Type.h" + +#include "lldb/API/SBDefines.h" + #include "lldb/API/SBType.h" #include "lldb/API/SBStream.h" #include "lldb/Core/ConstString.h" @@ -18,334 +24,340 @@ using namespace lldb; using namespace lldb_private; +using namespace clang; - -bool -SBType::IsPointerType (void *opaque_type) +SBType::SBType (lldb_private::ClangASTType type) : +m_opaque_ap(new TypeImpl(ClangASTType(type.GetASTContext(), + type.GetOpaqueQualType()))) { - LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); - - //if (log) - // log->Printf ("SBType::IsPointerType (%p)", opaque_type); - - bool ret_value = ClangASTContext::IsPointerType (opaque_type); - - if (log) - log->Printf ("SBType::IsPointerType (opaque_type=%p) ==> '%s'", opaque_type, (ret_value ? "true" : "false")); - - return ret_value; } +SBType::SBType (lldb::TypeSP type) : +m_opaque_ap(new TypeImpl(type)) +{} -SBType::SBType (void *ast, void *clang_type) : - m_ast (ast), - m_type (clang_type) +SBType::SBType (const SBType &rhs) { + if (rhs.m_opaque_ap.get() != NULL) + { + m_opaque_ap = std::auto_ptr<TypeImpl>(new TypeImpl(ClangASTType(rhs.m_opaque_ap->GetASTContext(), + rhs.m_opaque_ap->GetOpaqueQualType()))); + } } -SBType::SBType (const SBType &rhs) : - m_ast (rhs.m_ast), - m_type (rhs.m_type) +SBType::SBType (clang::ASTContext *ctx, clang_type_t ty) : +m_opaque_ap(new TypeImpl(ClangASTType(ctx, ty))) { } -const SBType & -SBType::operator =(const SBType &rhs) +SBType::SBType() : +m_opaque_ap(NULL) { - m_ast = rhs.m_ast; - m_type = rhs.m_type; - return *this; } -SBType::~SBType () -{ -} +SBType::SBType (TypeImpl impl) : +m_opaque_ap(&impl) +{} bool -SBType::IsValid () +SBType::operator == (const lldb::SBType &rhs) const { - return m_ast != NULL && m_type != NULL; + if (IsValid() == false) + return !rhs.IsValid(); + + return (rhs.m_opaque_ap->GetASTContext() == m_opaque_ap->GetASTContext()) + && + (rhs.m_opaque_ap->GetOpaqueQualType() == m_opaque_ap->GetOpaqueQualType()); } -const char * -SBType::GetName () -{ - if (IsValid ()) - return ClangASTType::GetConstTypeName (m_type).AsCString(NULL); - return NULL; +bool +SBType::operator != (const lldb::SBType &rhs) const +{ + if (IsValid() == false) + return rhs.IsValid(); + + return (rhs.m_opaque_ap->GetASTContext() != m_opaque_ap->GetASTContext()) + || + (rhs.m_opaque_ap->GetOpaqueQualType() != m_opaque_ap->GetOpaqueQualType()); } -uint64_t -SBType::GetByteSize() + +const lldb::SBType & +SBType::operator = (const lldb::SBType &rhs) { - if (IsValid ()) - return ClangASTType::GetClangTypeBitWidth (static_cast<clang::ASTContext *>(m_ast), m_type); - return NULL; + if (*this != rhs) + { + if (!rhs.IsValid()) + m_opaque_ap.reset(NULL); + else + m_opaque_ap = std::auto_ptr<TypeImpl>(new TypeImpl(ClangASTType(rhs.m_opaque_ap->GetASTContext(), + rhs.m_opaque_ap->GetOpaqueQualType()))); + } + return *this; } -Encoding -SBType::GetEncoding (uint32_t &count) +SBType::~SBType () +{} + +lldb_private::TypeImpl & +SBType::ref () { - if (IsValid ()) - return ClangASTType::GetEncoding (m_type, count); - count = 0; - return eEncodingInvalid; + if (m_opaque_ap.get() == NULL) + m_opaque_ap.reset (new lldb_private::TypeImpl()); + return *m_opaque_ap; } -uint64_t -SBType::GetNumberChildren (bool omit_empty_base_classes) +const lldb_private::TypeImpl & +SBType::ref () const { - if (IsValid ()) - return ClangASTContext::GetNumChildren (static_cast<clang::ASTContext *>(m_ast), - m_type, - omit_empty_base_classes); - return 0; + // "const SBAddress &addr" should already have checked "addr.IsValid()" + // prior to calling this function. In case you didn't we will assert + // and die to let you know. + assert (m_opaque_ap.get()); + return *m_opaque_ap; } - bool -SBType::GetChildAtIndex (bool omit_empty_base_classes, uint32_t idx, SBTypeMember &member) +SBType::IsValid() const { - void *child_clang_type = NULL; - bool ignore_array_bounds = false; - std::string child_name; - uint32_t child_byte_size = 0; - int32_t child_byte_offset = 0; - uint32_t child_bitfield_bit_size = 0; - uint32_t child_bitfield_bit_offset = 0; - bool child_is_base_class = false; - bool child_is_deref_of_parent = false; - - if (IsValid ()) - { - - child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (NULL, - static_cast<clang::ASTContext *>(m_ast), - NULL, - m_type, - idx, - false, // transparent pointers - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent); - - } + if (m_opaque_ap.get() == NULL) + return false; - if (child_clang_type) - { - member.m_ast = m_ast; - member.m_parent_type = m_type; - member.m_member_type = child_clang_type, - member.SetName (child_name.c_str()); - member.m_offset = child_byte_offset; - member.m_bit_size = child_bitfield_bit_size; - member.m_bit_offset = child_bitfield_bit_offset; - member.m_is_base_class = child_is_base_class; - member.m_is_deref_of_paremt = child_is_deref_of_parent; - } - else - { - member.Clear(); - } - - return child_clang_type != NULL; + return m_opaque_ap->IsValid(); } -uint32_t -SBType::GetChildIndexForName (bool omit_empty_base_classes, const char *name) +size_t +SBType::GetByteSize() const { - return ClangASTContext::GetIndexOfChildWithName (static_cast<clang::ASTContext *>(m_ast), - m_type, - name, - omit_empty_base_classes); + if (!IsValid()) + return 0; + + return ClangASTType::GetTypeByteSize(m_opaque_ap->GetASTContext(), m_opaque_ap->GetOpaqueQualType()); + } bool -SBType::IsAPointerType () -{ - return ClangASTContext::IsPointerType (m_type); -} - -SBType -SBType::GetPointeeType () +SBType::IsPointerType() const { - void *pointee_type = NULL; - if (IsAPointerType ()) - { - pointee_type = ClangASTType::GetPointeeType (m_type); - } - return SBType (pointee_type ? m_ast : NULL, pointee_type); + if (!IsValid()) + return false; + + QualType qt = QualType::getFromOpaquePtr(m_opaque_ap->GetOpaqueQualType()); + const clang::Type* typePtr = qt.getTypePtrOrNull(); + + if (typePtr) + return typePtr->isAnyPointerType(); + return false; } bool -SBType::GetDescription (SBStream &description) +SBType::IsReferenceType() const { - const char *name = GetName(); - uint64_t byte_size = GetByteSize(); - uint64_t num_children = GetNumberChildren (true); - bool is_ptr = IsAPointerType (); - - description.Printf ("type_name: %s, size: %d bytes", (name != NULL ? name : "<unknown type name>"), byte_size); - if (is_ptr) - { - SBType pointee_type = GetPointeeType(); - const char *pointee_name = pointee_type.GetName(); - description.Printf (", (* %s)", (pointee_name != NULL ? pointee_name : "<unknown type name>")); - } - else if (num_children > 0) - { - description.Printf (", %d members:\n", num_children); - for (uint32_t i = 0; i < num_children; ++i) - { - SBTypeMember field; - GetChildAtIndex (true, i, field); - const char *field_name = field.GetName(); - SBType field_type = field.GetType(); - const char *field_type_name = field_type.GetName(); - - description.Printf (" %s (type: %s", (field_name != NULL ? field_name : "<unknown member name>"), - (field_type_name != NULL ? field_type_name : "<unknown type name>")); - - if (field.IsBitfield()) - { - size_t width = field.GetBitfieldWidth (); - description.Printf (" , %d bits", (int) width); - } - description.Printf (")\n"); - } - } - return true; -} + if (!IsValid()) + return false; -SBTypeMember::SBTypeMember () : - m_ast (NULL), - m_parent_type (NULL), - m_member_type (NULL), - m_member_name (NULL), - m_offset (0), - m_bit_size (0), - m_bit_offset (0), - m_is_base_class (false) + QualType qt = QualType::getFromOpaquePtr(m_opaque_ap->GetOpaqueQualType()); + const clang::Type* typePtr = qt.getTypePtrOrNull(); -{ + if (typePtr) + return typePtr->isReferenceType(); + return false; } -SBTypeMember::SBTypeMember (const SBTypeMember &rhs) : - m_ast (rhs.m_ast), - m_parent_type (rhs.m_parent_type), - m_member_type (rhs.m_member_type), - m_member_name (rhs.m_member_name), - m_offset (rhs.m_offset), - m_bit_size (rhs.m_bit_size), - m_bit_offset (rhs.m_bit_offset), - m_is_base_class (rhs.m_is_base_class) +SBType +SBType::GetPointerType() const { -} + if (!IsValid()) + return SBType(); -const SBTypeMember& -SBTypeMember::operator =(const SBTypeMember &rhs) -{ - if (this != &rhs) - { - m_ast = rhs.m_ast; - m_parent_type = rhs.m_parent_type; - m_member_type = rhs.m_member_type; - m_member_name = rhs.m_member_name; - m_offset = rhs.m_offset; - m_bit_size = rhs.m_bit_size; - m_bit_offset = rhs.m_bit_offset; - m_is_base_class = rhs.m_is_base_class; - } - return *this; + return SBType(m_opaque_ap->GetASTContext(), + ClangASTContext::CreatePointerType(m_opaque_ap->GetASTContext(), m_opaque_ap->GetOpaqueQualType())); } -SBTypeMember::~SBTypeMember () +SBType +SBType::GetPointeeType() const { - SetName (NULL); -} + if (!IsValid()) + return SBType(); -void -SBTypeMember::SetName (const char *name) -{ - if (m_member_name) - free (m_member_name); - if (name && name[0]) - m_member_name = ::strdup (name); - else - m_member_name = NULL; + QualType qt = QualType::getFromOpaquePtr(m_opaque_ap->GetOpaqueQualType()); + const clang::Type* typePtr = qt.getTypePtrOrNull(); + + if (typePtr) + return SBType(m_opaque_ap->GetASTContext(),typePtr->getPointeeType().getAsOpaquePtr()); + return SBType(); } -void -SBTypeMember::Clear() +SBType +SBType::GetReferenceType() const { - m_ast = NULL; - m_parent_type = NULL; - m_member_type = NULL; - SetName (NULL); - m_offset = 0; - m_bit_size = 0; - m_bit_offset = 0; - m_is_base_class = false; + if (!IsValid()) + return SBType(); + + return SBType(m_opaque_ap->GetASTContext(), + ClangASTContext::CreateLValueReferenceType(m_opaque_ap->GetASTContext(), m_opaque_ap->GetOpaqueQualType())); } -bool -SBTypeMember::IsValid () +SBType +SBType::GetDereferencedType() const { - return m_member_type != NULL; + if (!IsValid()) + return SBType(); + + QualType qt = QualType::getFromOpaquePtr(m_opaque_ap->GetOpaqueQualType()); + + return SBType(m_opaque_ap->GetASTContext(),qt.getNonReferenceType().getAsOpaquePtr()); } -bool -SBTypeMember::IsBitfield () +SBType +SBType::GetBasicType(lldb::BasicType type) const { - return m_bit_size != 0; + + if (!IsValid()) + return SBType(); + + clang::CanQualType base_type_qual; + + switch (type) + { + case eBasicTypeChar: + base_type_qual = m_opaque_ap->GetASTContext()->CharTy; + break; + case eBasicTypeSignedChar: + base_type_qual = m_opaque_ap->GetASTContext()->SignedCharTy; + break; + case eBasicTypeShort: + base_type_qual = m_opaque_ap->GetASTContext()->ShortTy; + break; + case eBasicTypeUnsignedShort: + base_type_qual = m_opaque_ap->GetASTContext()->UnsignedShortTy; + break; + case eBasicTypeInt: + base_type_qual = m_opaque_ap->GetASTContext()->IntTy; + break; + case eBasicTypeUnsignedInt: + base_type_qual = m_opaque_ap->GetASTContext()->UnsignedIntTy; + break; + case eBasicTypeLong: + base_type_qual = m_opaque_ap->GetASTContext()->LongTy; + break; + case eBasicTypeUnsignedLong: + base_type_qual = m_opaque_ap->GetASTContext()->UnsignedLongTy; + break; + case eBasicTypeBool: + base_type_qual = m_opaque_ap->GetASTContext()->BoolTy; + break; + case eBasicTypeFloat: + base_type_qual = m_opaque_ap->GetASTContext()->FloatTy; + break; + case eBasicTypeDouble: + base_type_qual = m_opaque_ap->GetASTContext()->DoubleTy; + break; + case eBasicTypeObjCID: + base_type_qual = m_opaque_ap->GetASTContext()->ObjCBuiltinIdTy; + break; + case eBasicTypeVoid: + base_type_qual = m_opaque_ap->GetASTContext()->VoidTy; + break; + case eBasicTypeWChar: + base_type_qual = m_opaque_ap->GetASTContext()->WCharTy; + break; + case eBasicTypeChar16: + base_type_qual = m_opaque_ap->GetASTContext()->Char16Ty; + break; + case eBasicTypeChar32: + base_type_qual = m_opaque_ap->GetASTContext()->Char32Ty; + break; + case eBasicTypeLongLong: + base_type_qual = m_opaque_ap->GetASTContext()->LongLongTy; + break; + case eBasicTypeUnsignedLongLong: + base_type_qual = m_opaque_ap->GetASTContext()->UnsignedLongLongTy; + break; + case eBasicTypeInt128: + base_type_qual = m_opaque_ap->GetASTContext()->Int128Ty; + break; + case eBasicTypeUnsignedInt128: + base_type_qual = m_opaque_ap->GetASTContext()->UnsignedInt128Ty; + break; + case eBasicTypeLongDouble: + base_type_qual = m_opaque_ap->GetASTContext()->LongDoubleTy; + break; + case eBasicTypeFloatComplex: + base_type_qual = m_opaque_ap->GetASTContext()->FloatComplexTy; + break; + case eBasicTypeDoubleComplex: + base_type_qual = m_opaque_ap->GetASTContext()->DoubleComplexTy; + break; + case eBasicTypeLongDoubleComplex: + base_type_qual = m_opaque_ap->GetASTContext()->LongDoubleComplexTy; + break; + case eBasicTypeObjCClass: + base_type_qual = m_opaque_ap->GetASTContext()->ObjCBuiltinClassTy; + break; + case eBasicTypeObjCSel: + base_type_qual = m_opaque_ap->GetASTContext()->ObjCBuiltinSelTy; + break; + default: + return SBType(); + } + + return SBType(m_opaque_ap->GetASTContext(), + base_type_qual.getAsOpaquePtr()); } -size_t -SBTypeMember::GetBitfieldWidth () +const char* +SBType::GetName() { - return m_bit_size; + if (!IsValid()) + return ""; + + return ClangASTType::GetConstTypeName(m_opaque_ap->GetOpaqueQualType()).GetCString(); } -size_t -SBTypeMember::GetBitfieldOffset () +SBTypeList::SBTypeList() : +m_opaque_ap(new TypeListImpl()) { - return m_bit_offset; } -bool -SBTypeMember::IsBaseClass () +SBTypeList::SBTypeList(const SBTypeList& rhs) : +m_opaque_ap(new TypeListImpl()) { - return m_is_base_class; + for (int j = 0; j < rhs.GetSize(); j++) + AppendType(rhs.GetTypeAtIndex(j)); } -size_t -SBTypeMember::GetOffset () +SBTypeList& +SBTypeList::operator = (const SBTypeList& rhs) { - return m_offset; + if (m_opaque_ap.get() != rhs.m_opaque_ap.get()) + { + m_opaque_ap.reset(new TypeListImpl()); + for (int j = 0; j < rhs.GetSize(); j++) + AppendType(rhs.GetTypeAtIndex(j)); + } + return *this; } -SBType -SBTypeMember::GetType() +void +SBTypeList::AppendType(SBType type) { - return SBType (m_ast, m_member_type); + if (type.IsValid()) + m_opaque_ap->AppendType(*type.m_opaque_ap.get()); } SBType -SBTypeMember::GetParentType() +SBTypeList::GetTypeAtIndex(int index) const { - return SBType (m_ast, m_parent_type); + return SBType(m_opaque_ap->GetTypeAtIndex(index)); } - -const char * -SBTypeMember::GetName () +int +SBTypeList::GetSize() const { - return m_member_name; + return m_opaque_ap->GetSize(); } +SBTypeList::~SBTypeList() +{ +}
\ No newline at end of file diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index 2528f4c361f..229eba5f5d6 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -17,6 +17,7 @@ #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" @@ -156,9 +157,9 @@ SBValue::IsInScope () if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTarget()) + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) { - Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); result = m_opaque_sp->IsInScope (); } } @@ -182,9 +183,9 @@ SBValue::GetValue () const char *cstr = NULL; if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTarget()) + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) { - Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); cstr = m_opaque_sp->GetValueAsCString (); } } @@ -237,9 +238,9 @@ SBValue::GetObjectDescription () const char *cstr = NULL; if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTarget()) + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) { - Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); cstr = m_opaque_sp->GetObjectDescription (); } } @@ -260,15 +261,39 @@ SBValue::GetValueDidChange (const SBFrame &sb_frame) return GetValueDidChange (); } +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(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().GetTarget()) + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) { - Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); result = m_opaque_sp->GetValueDidChange (); } } @@ -291,9 +316,9 @@ SBValue::GetSummary () const char *cstr = NULL; if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTarget()) + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) { - Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); cstr = m_opaque_sp->GetSummaryAsCString(); } } @@ -320,9 +345,9 @@ SBValue::GetLocation () const char *cstr = NULL; if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTarget()) + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) { - Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); cstr = m_opaque_sp->GetLocationAsCString(); } } @@ -349,22 +374,109 @@ SBValue::SetValueFromCString (const char *value_str) bool success = false; if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTarget()) + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) { - Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + 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, const SBType& type) +{ + lldb::SBValue result; + if (m_opaque_sp) + { + if (type.IsValid()) + { + result = SBValue(m_opaque_sp->GetSyntheticChildAtOffset(offset, *type.m_opaque_ap->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.get()); + else + log->Printf ("SBValue(%p)::GetChildAtOffset => NULL", m_opaque_sp.get()); + } + return result; +} + +lldb::SBValue +SBValue::Cast(const 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(), + true, true, 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.get()); + else + log->Printf ("SBValue(%p)::GetChildFromExpression => NULL", m_opaque_sp.get()); + } + return result; +} + +lldb::SBValue +SBValue::CreateValueFromAddress(const char* name, lldb::addr_t address, const 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 result_valobj_sp(ValueObjectConstResult::Create(m_opaque_sp->GetUpdatePoint().GetExecutionContextScope(), + real_type.m_opaque_ap->GetASTContext(), + real_type.m_opaque_ap->GetOpaqueQualType(), + ConstString(name), + buffer, + lldb::endian::InlHostByteOrder(), + GetTarget().GetProcess().GetAddressByteSize())); + + 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.get()); + else + log->Printf ("SBValue(%p)::GetChildFromAddress => 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().GetTarget()->GetPreferDynamicValue(); + use_dynamic = m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetPreferDynamicValue(); return GetChildAtIndex (idx, use_dynamic, can_create_synthetic); } @@ -375,9 +487,9 @@ SBValue::GetChildAtIndex (uint32_t idx, lldb::DynamicValueType use_dynamic, bool if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTarget()) + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) { - Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + 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) @@ -418,9 +530,9 @@ SBValue::GetIndexOfChildWithName (const char *name) uint32_t idx = UINT32_MAX; if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTarget()) + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) { - Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); idx = m_opaque_sp->GetIndexOfChildWithName (ConstString(name)); } @@ -441,7 +553,7 @@ SBValue::GetChildMemberWithName (const char *name) { if (m_opaque_sp) { - lldb::DynamicValueType use_dynamic_value = m_opaque_sp->GetUpdatePoint().GetTarget()->GetPreferDynamicValue(); + lldb::DynamicValueType use_dynamic_value = m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetPreferDynamicValue(); return GetChildMemberWithName (name, use_dynamic_value); } else @@ -457,9 +569,9 @@ SBValue::GetChildMemberWithName (const char *name, lldb::DynamicValueType use_dy if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTarget()) + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) { - Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + 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) { @@ -488,9 +600,9 @@ SBValue::GetValueForExpressionPath(const char* expr_path) lldb::ValueObjectSP child_sp; if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTarget()) + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) { - Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + 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); } @@ -512,9 +624,9 @@ SBValue::GetNumChildren () if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTarget()) + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) { - Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); num_children = m_opaque_sp->GetNumChildren(); } @@ -534,9 +646,9 @@ SBValue::Dereference () SBValue sb_value; if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTarget()) + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) { - Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); Error error; sb_value = m_opaque_sp->Dereference (error); @@ -556,9 +668,9 @@ SBValue::TypeIsPointerType () if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTarget()) + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) { - Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); is_ptr_type = m_opaque_sp->IsPointerType(); } @@ -577,9 +689,9 @@ SBValue::GetOpaqueType() { if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTarget()) + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) { - Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); return m_opaque_sp->GetClangType(); } @@ -587,6 +699,95 @@ SBValue::GetOpaqueType() 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) + { + if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) + { + result = SBProcess(lldb::ProcessSP(m_opaque_sp->GetUpdatePoint().GetTargetSP()->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(lldb::ThreadSP(m_opaque_sp->GetUpdatePoint().GetExecutionContextScope()->CalculateThread())); + } + } + 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 = SBFrame(lldb::StackFrameSP(m_opaque_sp->GetUpdatePoint().GetExecutionContextScope()->CalculateStackFrame())); + } + } + 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 @@ -685,3 +886,23 @@ SBValue::SetFormat (lldb::Format format) m_opaque_sp->SetFormat(format); } +lldb::SBValue +SBValue::AddressOf() +{ + 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->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; +}
\ No newline at end of file diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 814a2ad3144..5820c39a329 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -1367,11 +1367,11 @@ LookupTypeInModule (CommandInterpreter &interpreter, { if (module && name_cstr && name_cstr[0]) { - SymbolContextList sc_list; + /*SymbolContextList sc_list; SymbolVendor *symbol_vendor = module->GetSymbolVendor(); if (symbol_vendor) - { + {*/ TypeList type_list; uint32_t num_matches = 0; SymbolContext sc; @@ -1383,7 +1383,7 @@ LookupTypeInModule (CommandInterpreter &interpreter, // else // { ConstString name(name_cstr); - num_matches = symbol_vendor->FindTypes(sc, name, true, UINT32_MAX, type_list); + num_matches = module->FindTypes(sc, name, true, UINT32_MAX, type_list); // } if (num_matches) @@ -1407,7 +1407,7 @@ LookupTypeInModule (CommandInterpreter &interpreter, } } return num_matches; - } + //} } return 0; } diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp index e47ccc700a0..959432a1203 100644 --- a/lldb/source/Commands/CommandObjectType.cpp +++ b/lldb/source/Commands/CommandObjectType.cpp @@ -218,8 +218,8 @@ CommandObjectTypeFormatAdd::CommandOptions::g_option_table[] = { { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade to derived typedefs."}, { LLDB_OPT_SET_ALL, false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat, "The format to use to display this type."}, - { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeBoolean, "Don't use this format for pointers-to-type objects."}, - { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeBoolean, "Don't use this format for references-to-type objects."}, + { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, + { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -1074,16 +1074,16 @@ CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = { { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade to derived typedefs."}, - { LLDB_OPT_SET_ALL, false, "no-value", 'v', no_argument, NULL, 0, eArgTypeBoolean, "Don't show the value, just show the summary, for this type."}, - { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeBoolean, "Don't use this format for pointers-to-type objects."}, - { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeBoolean, "Don't use this format for references-to-type objects."}, - { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeBoolean, "Type names are actually regular expressions."}, - { LLDB_OPT_SET_1 , true, "inline-children", 'c', no_argument, NULL, 0, eArgTypeBoolean, "If true, inline all child values into summary string."}, + { LLDB_OPT_SET_ALL, false, "no-value", 'v', no_argument, NULL, 0, eArgTypeNone, "Don't show the value, just show the summary, for this type."}, + { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, + { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, + { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, + { LLDB_OPT_SET_1 , true, "inline-children", 'c', no_argument, NULL, 0, eArgTypeNone, "If true, inline all child values into summary string."}, { LLDB_OPT_SET_2 , true, "format-string", 'f', required_argument, NULL, 0, eArgTypeSummaryString, "Format string used to display text and object contents."}, { LLDB_OPT_SET_3, false, "python-script", 's', required_argument, NULL, 0, eArgTypeName, "Give a one-liner Python script as part of the command."}, { LLDB_OPT_SET_3, false, "python-function", 'F', required_argument, NULL, 0, eArgTypeName, "Give the name of a Python function to use for this type."}, - { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeName, "Input Python code to use for this type manually."}, - { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', no_argument, NULL, 0, eArgTypeBoolean, "Expand aggregate data types to show children on separate lines."}, + { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone, "Input Python code to use for this type manually."}, + { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', no_argument, NULL, 0, eArgTypeNone, "Expand aggregate data types to show children on separate lines."}, { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', required_argument, NULL, 0, eArgTypeName, "A name for this summary string."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -1249,7 +1249,7 @@ public: OptionDefinition CommandObjectTypeSummaryDelete::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeBoolean, "Delete from every category."}, + { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Delete from every category."}, { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Delete from given category."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -1375,7 +1375,7 @@ public: OptionDefinition CommandObjectTypeSummaryClear::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeBoolean, "Clear every category."}, + { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Clear every category."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -2236,7 +2236,7 @@ public: OptionDefinition CommandObjectTypeSynthDelete::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeBoolean, "Delete from every category."}, + { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Delete from every category."}, { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Delete from given category."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -2363,7 +2363,7 @@ public: OptionDefinition CommandObjectTypeSynthClear::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeBoolean, "Clear every category."}, + { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Clear every category."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -2377,6 +2377,9 @@ static const char *g_synth_addreader_instructions = "Enter your Python command " def num_children(self):\n" " def get_child_at_index(self, index):\n" " def get_child_index(self, name):\n" + "Optionally, you can also define a method:\n" + " def update(self):\n" + "if your synthetic provider is holding on to any per-object state variables (currently, this is not implemented because of the way LLDB handles instances of SBValue and you should not rely on object persistence and per-object state)\n" "class synthProvider:"; class TypeSynthAddInputReader : public InputReaderEZ @@ -2832,12 +2835,12 @@ OptionDefinition CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] = { { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade to derived typedefs."}, - { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeBoolean, "Don't use this format for pointers-to-type objects."}, - { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeBoolean, "Don't use this format for references-to-type objects."}, + { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, + { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, { LLDB_OPT_SET_1, false, "child", 'c', required_argument, NULL, 0, eArgTypeName, "Include this expression path in the synthetic view."}, { LLDB_OPT_SET_2, false, "python-class", 'l', required_argument, NULL, 0, eArgTypeName, "Use this Python class to produce synthetic children."}, - { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeBoolean, "Type Python code to generate a class that provides synthetic children."}, + { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index dff2eb00fe8..a217ddb36ec 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -1004,16 +1004,28 @@ Debugger::FormatPrompt switch (var_name_begin[0]) { case '*': - { - if (!vobj) - break; - do_deref_pointer = true; - var_name_begin++; - } - // Fall through... - case 'v': + case 's': { + if (!vobj) + break; + + // check for *var and *svar + if (*var_name_begin == '*') + { + do_deref_pointer = true; + var_name_begin++; + } + if (*var_name_begin == 's') + { + vobj = vobj->GetSyntheticValue(lldb::eUseSyntheticFilter).get(); + var_name_begin++; + } + + // should be a 'v' by now + if (*var_name_begin != 'v') + break; + ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? ValueObject::eDereference : ValueObject::eNothing); ValueObject::GetValueForExpressionPathOptions options; diff --git a/lldb/source/Core/FormatClasses.cpp b/lldb/source/Core/FormatClasses.cpp index e321a40a310..046cc705d00 100644 --- a/lldb/source/Core/FormatClasses.cpp +++ b/lldb/source/Core/FormatClasses.cpp @@ -171,7 +171,7 @@ m_python_class(pclass) return; } - m_interpreter = be->GetUpdatePoint().GetTarget()->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); + m_interpreter = be->GetUpdatePoint().GetTargetSP()->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); if (m_interpreter == NULL) m_wrapper = NULL; diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index 8b07a76eead..28780f4f99a 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -422,7 +422,7 @@ Module::FindFunctions (const RegularExpression& regex, } uint32_t -Module::FindTypes (const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, TypeList& types) +Module::FindTypes_Impl (const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, TypeList& types) { Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); if (sc.module_sp.get() == NULL || sc.module_sp.get() == this) @@ -434,6 +434,41 @@ Module::FindTypes (const SymbolContext& sc, const ConstString &name, bool append return 0; } +// depending on implementation details, type lookup might fail because of +// embedded spurious namespace:: prefixes. this call strips them, paying +// attention to the fact that a type might have namespace'd type names as +// arguments to templates, and those must not be stripped off +static const char* +StripTypeName(const char* name_cstr) +{ + const char* skip_namespace = strstr(name_cstr, "::"); + const char* template_arg_char = strchr(name_cstr, '<'); + while (skip_namespace != NULL) + { + if (template_arg_char != NULL && + skip_namespace > template_arg_char) // but namespace'd template arguments are still good to go + break; + name_cstr = skip_namespace+2; + skip_namespace = strstr(name_cstr, "::"); + } + return name_cstr; +} + +uint32_t +Module::FindTypes (const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, TypeList& types) +{ + uint32_t retval = FindTypes_Impl(sc, name, append, max_matches, types); + + if (retval == 0) + { + const char *stripped = StripTypeName(name.GetCString()); + return FindTypes_Impl(sc, ConstString(stripped), append, max_matches, types); + } + else + return retval; + +} + //uint32_t //Module::FindTypes(const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, Type::Encoding encoding, const char *udt_name, TypeList& types) //{ diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index b063d1647d7..d27b30eabfa 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -389,7 +389,7 @@ ModuleList::FindModule (const UUID &uuid) uint32_t -ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, TypeList& types) +ModuleList::FindTypes_Impl (const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, TypeList& types) { Mutex::Locker locker(m_modules_mutex); @@ -409,6 +409,40 @@ ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool ap return total_matches; } +// depending on implementation details, type lookup might fail because of +// embedded spurious namespace:: prefixes. this call strips them, paying +// attention to the fact that a type might have namespace'd type names as +// arguments to templates, and those must not be stripped off +static const char* +StripTypeName(const char* name_cstr) +{ + const char* skip_namespace = strstr(name_cstr, "::"); + const char* template_arg_char = strchr(name_cstr, '<'); + while (skip_namespace != NULL) + { + if (template_arg_char != NULL && + skip_namespace > template_arg_char) // but namespace'd template arguments are still good to go + break; + name_cstr = skip_namespace+2; + skip_namespace = strstr(name_cstr, "::"); + } + return name_cstr; +} + +uint32_t +ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, TypeList& types) +{ + uint32_t retval = FindTypes_Impl(sc, name, append, max_matches, types); + + if (retval == 0) + { + const char *stripped = StripTypeName(name.GetCString()); + return FindTypes_Impl(sc, ConstString(stripped), append, max_matches, types); + } + else + return retval; + +} ModuleSP ModuleList::FindFirstModuleForFileSpec (const FileSpec &file_spec, diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index a98d0beae93..1ab72c8005b 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -20,6 +20,7 @@ // Project includes #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Debugger.h" +#include "lldb/Core/Log.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectChild.h" #include "lldb/Core/ValueObjectConstResult.h" @@ -89,6 +90,7 @@ ValueObject::ValueObject (ValueObject &parent) : m_is_array_item_for_pointer(false), m_is_bitfield_for_scalar(false), m_is_expression_path_child(false), + m_is_child_at_offset(false), m_dump_printable_counter(0) { m_manager->ManageObject(this); @@ -132,6 +134,7 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope) : m_is_array_item_for_pointer(false), m_is_bitfield_for_scalar(false), m_is_expression_path_child(false), + m_is_child_at_offset(false), m_dump_printable_counter(0) { m_manager = new ValueObjectManager(); @@ -203,9 +206,12 @@ ValueObject::UpdateValueIfNeeded (bool update_format) void ValueObject::UpdateFormatsIfNeeded() { - /*printf("CHECKING FOR UPDATES. I am at revision %d, while the format manager is at revision %d\n", + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); + if (log) + log->Printf("checking for FormatManager revisions. VO named %s is at revision %d, while the format manager is at revision %d", + GetName().GetCString(), m_last_format_mgr_revision, - Debugger::ValueFormats::GetCurrentRevision());*/ + Debugger::Formatting::ValueFormats::GetCurrentRevision()); if (HasCustomSummaryFormat() && m_update_point.GetUpdateID() != m_user_id_of_forced_summary) { ClearCustomSummaryFormat(); @@ -441,12 +447,6 @@ ValueObject::SetNumChildren (uint32_t num_children) } void -ValueObject::SetName (const char *name) -{ - m_name.SetCString(name); -} - -void ValueObject::SetName (const ConstString &name) { m_name = name; @@ -640,7 +640,11 @@ ValueObject::ReadPointedString(Stream& s, if (exe_scope) { Target *target = exe_scope->CalculateTarget(); - if (target != NULL) + if (target == NULL) + { + s << "<no target to read from>"; + } + else { lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS; AddressType cstr_address_type = eAddressTypeInvalid; @@ -663,7 +667,11 @@ ValueObject::ReadPointedString(Stream& s, // We have a pointer cstr_address = GetPointerValue (cstr_address_type, true); } - if (cstr_address != LLDB_INVALID_ADDRESS) + if (cstr_address == LLDB_INVALID_ADDRESS) + { + s << "<invalid address for data>"; + } + else { Address cstr_so_addr (NULL, cstr_address); DataExtractor data; @@ -695,6 +703,8 @@ ValueObject::ReadPointedString(Stream& s, s << "..."; s << '"'; } + else + s << "\"<data not available>\""; } else { @@ -706,6 +716,8 @@ ValueObject::ReadPointedString(Stream& s, s << '"'; + bool any_data = false; + data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder()); while ((bytes_read = target->ReadMemory (cstr_so_addr, prefer_file_cache, @@ -713,6 +725,7 @@ ValueObject::ReadPointedString(Stream& s, k_max_buf_size, error)) > 0) { + any_data = true; size_t len = strlen(&data_buffer.front()); if (len == 0) break; @@ -741,6 +754,10 @@ ValueObject::ReadPointedString(Stream& s, cstr_len -= len; cstr_so_addr.Slide (k_max_buf_size); } + + if (any_data == false) + s << "<data not available>"; + s << '"'; } } @@ -750,6 +767,7 @@ ValueObject::ReadPointedString(Stream& s, else { error.SetErrorString("impossible to read a string from this object"); + s << "<not a string object>"; } } @@ -1350,7 +1368,7 @@ ValueObject::GetSyntheticArrayMemberFromPointer (int32_t index, bool can_create) { AddSyntheticChild(index_const_str, synthetic_child); synthetic_child_sp = synthetic_child->GetSP(); - synthetic_child_sp->SetName(index_str); + synthetic_child_sp->SetName(ConstString(index_str)); synthetic_child_sp->m_is_array_item_for_pointer = true; } } @@ -1393,7 +1411,7 @@ ValueObject::GetSyntheticArrayMemberFromArray (int32_t index, bool can_create) { AddSyntheticChild(index_const_str, synthetic_child); synthetic_child_sp = synthetic_child->GetSP(); - synthetic_child_sp->SetName(index_str); + synthetic_child_sp->SetName(ConstString(index_str)); synthetic_child_sp->m_is_array_item_for_pointer = true; } } @@ -1434,7 +1452,7 @@ ValueObject::GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_cre { AddSyntheticChild(index_const_str, synthetic_child); synthetic_child_sp = synthetic_child->GetSP(); - synthetic_child_sp->SetName(index_str); + synthetic_child_sp->SetName(ConstString(index_str)); synthetic_child_sp->m_is_bitfield_for_scalar = true; } } @@ -1442,6 +1460,46 @@ ValueObject::GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_cre return synthetic_child_sp; } +lldb::ValueObjectSP +ValueObject::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create) +{ + + ValueObjectSP synthetic_child_sp; + + char name_str[64]; + snprintf(name_str, sizeof(name_str), "@%i", offset); + ConstString name_const_str(name_str); + + // Check if we have already created a synthetic array member in this + // valid object. If we have we will re-use it. + synthetic_child_sp = GetSyntheticChild (name_const_str); + + if (synthetic_child_sp.get()) + return synthetic_child_sp; + + if (!can_create) + return lldb::ValueObjectSP(); + + ValueObjectChild *synthetic_child = new ValueObjectChild(*this, + type.GetASTContext(), + type.GetOpaqueQualType(), + name_const_str, + type.GetTypeByteSize(), + offset, + 0, + 0, + false, + false); + if (synthetic_child) + { + AddSyntheticChild(name_const_str, synthetic_child); + synthetic_child_sp = synthetic_child->GetSP(); + synthetic_child_sp->SetName(name_const_str); + synthetic_child_sp->m_is_child_at_offset = true; + } + return synthetic_child_sp; +} + // your expression path needs to have a leading . or -> // (unless it somehow "looks like" an array, in which case it has // a leading [ symbol). while the [ is meaningful and should be shown @@ -1477,7 +1535,7 @@ ValueObject::GetSyntheticExpressionPathChild(const char* expression, bool can_cr if (synthetic_child_sp.get()) { AddSyntheticChild(name_const_string, synthetic_child_sp.get()); - synthetic_child_sp->SetName(SkipLeadingExpressionPathSeparators(expression)); + synthetic_child_sp->SetName(ConstString(SkipLeadingExpressionPathSeparators(expression))); synthetic_child_sp->m_is_expression_path_child = true; } } @@ -1508,7 +1566,7 @@ ValueObject::CalculateDynamicValue (lldb::DynamicValueType use_dynamic) if (!m_dynamic_value && !IsDynamic()) { - Process *process = m_update_point.GetProcess(); + Process *process = m_update_point.GetProcessSP().get(); bool worth_having_dynamic_value = false; diff --git a/lldb/source/Core/ValueObjectDynamicValue.cpp b/lldb/source/Core/ValueObjectDynamicValue.cpp index c80fd9d592f..885e68fd3bd 100644 --- a/lldb/source/Core/ValueObjectDynamicValue.cpp +++ b/lldb/source/Core/ValueObjectDynamicValue.cpp @@ -40,7 +40,7 @@ ValueObjectDynamicValue::ValueObjectDynamicValue (ValueObject &parent, lldb::Dyn m_type_sp(), m_use_dynamic (use_dynamic) { - SetName (parent.GetName().AsCString()); + SetName (parent.GetName()); } ValueObjectDynamicValue::~ValueObjectDynamicValue() @@ -134,7 +134,7 @@ ValueObjectDynamicValue::UpdateValue () } // First make sure our Type and/or Address haven't changed: - Process *process = m_update_point.GetProcess(); + Process *process = m_update_point.GetProcessSP().get(); if (!process) return false; @@ -201,7 +201,7 @@ ValueObjectDynamicValue::UpdateValue () // We've moved, so we should be fine... m_address = dynamic_address; - lldb::addr_t load_address = m_address.GetLoadAddress(m_update_point.GetTarget()); + lldb::addr_t load_address = m_address.GetLoadAddress(m_update_point.GetTargetSP().get()); m_value.GetScalar() = load_address; } diff --git a/lldb/source/Core/ValueObjectMemory.cpp b/lldb/source/Core/ValueObjectMemory.cpp index bfa58378911..098c0fb6410 100644 --- a/lldb/source/Core/ValueObjectMemory.cpp +++ b/lldb/source/Core/ValueObjectMemory.cpp @@ -62,9 +62,9 @@ ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope, { // Do not attempt to construct one of these objects with no variable! assert (m_type_sp.get() != NULL); - SetName (name); + SetName (ConstString(name)); m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); - lldb::addr_t load_address = m_address.GetLoadAddress(m_update_point.GetTarget()); + lldb::addr_t load_address = m_address.GetLoadAddress(m_update_point.GetTargetSP().get()); if (load_address != LLDB_INVALID_ADDRESS) { m_value.SetValueType(Value::eValueTypeLoadAddress); @@ -99,9 +99,9 @@ ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope, assert (m_clang_type.GetASTContext()); assert (m_clang_type.GetOpaqueQualType()); - SetName (name); + SetName (ConstString(name)); m_value.SetContext(Value::eContextTypeClangType, m_clang_type.GetOpaqueQualType()); - lldb::addr_t load_address = m_address.GetLoadAddress(m_update_point.GetTarget()); + lldb::addr_t load_address = m_address.GetLoadAddress(m_update_point.GetTargetSP().get()); if (load_address != LLDB_INVALID_ADDRESS) { m_value.SetValueType(Value::eValueTypeLoadAddress); diff --git a/lldb/source/Core/ValueObjectSyntheticFilter.cpp b/lldb/source/Core/ValueObjectSyntheticFilter.cpp index 252780cf11f..03b9f12ab91 100644 --- a/lldb/source/Core/ValueObjectSyntheticFilter.cpp +++ b/lldb/source/Core/ValueObjectSyntheticFilter.cpp @@ -44,7 +44,7 @@ ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::Synthetic m_children_byindex(), m_name_toindex() { - SetName (parent.GetName().AsCString()); + SetName (parent.GetName()); } ValueObjectSynthetic::~ValueObjectSynthetic() @@ -120,6 +120,10 @@ ValueObjectSynthetic::UpdateValue () m_children_byindex.clear(); m_name_toindex.clear(); + // let our backend do its update + + m_synth_filter->Update(); + SetValueIsValid(true); return true; } diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp index 27c7badca38..94b04e72944 100644 --- a/lldb/source/Interpreter/ScriptInterpreter.cpp +++ b/lldb/source/Interpreter/ScriptInterpreter.cpp @@ -98,7 +98,8 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call SWIGPythonCalculateNumChildren python_swig_calc_children, SWIGPythonGetChildAtIndex python_swig_get_child_index, SWIGPythonGetIndexOfChildWithName python_swig_get_index_child, - SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue) + SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue, + SWIGPythonUpdateSynthProviderInstance python_swig_update_provider) { ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback, python_swig_breakpoint_callback, @@ -107,7 +108,8 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call python_swig_calc_children, python_swig_get_child_index, python_swig_get_index_child, - python_swig_cast_to_sbvalue); + python_swig_cast_to_sbvalue, + python_swig_update_provider); } void diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index 82cad851028..e7c68e74da9 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -40,6 +40,7 @@ static ScriptInterpreter::SWIGPythonCalculateNumChildren g_swig_calc_children = static ScriptInterpreter::SWIGPythonGetChildAtIndex g_swig_get_child_index = NULL; static ScriptInterpreter::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = NULL; static ScriptInterpreter::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = NULL; +static ScriptInterpreter::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = NULL; static int _check_and_flush (FILE *stream) @@ -1307,7 +1308,7 @@ ScriptInterpreterPython::CreateSyntheticScriptedProvider (std::string class_name if (!valobj.get()) return NULL; - Target *target = valobj->GetUpdatePoint().GetTarget(); + Target *target = valobj->GetUpdatePoint().GetTargetSP().get(); if (!target) return NULL; @@ -1430,7 +1431,7 @@ ScriptInterpreterPython::CallPythonScriptFunction (const char *python_function_n if (!valobj.get()) return "<no object>"; - Target *target = valobj->GetUpdatePoint().GetTarget(); + Target *target = valobj->GetUpdatePoint().GetTargetSP().get(); if (!target) return "<no target>"; @@ -1768,6 +1769,38 @@ ScriptInterpreterPython::GetIndexOfChildWithName (void *implementor, const char* return ret_val; } +void +ScriptInterpreterPython::UpdateSynthProviderInstance (void* implementor) +{ + if (!implementor) + return; + + if (!g_swig_update_provider) + return; + + ScriptInterpreterPython *python_interpreter = this; + + FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); + if (CurrentThreadHasPythonLock()) + { + python_interpreter->EnterSession (); + g_swig_update_provider (implementor); + python_interpreter->LeaveSession (); + } + else + { + while (!GetPythonLock (1)) + fprintf (tmp_fh, + "Python interpreter locked on another thread; waiting to acquire lock...\n"); + python_interpreter->EnterSession (); + g_swig_update_provider (implementor); + python_interpreter->LeaveSession (); + ReleasePythonLock (); + } + + return; +} + lldb::SBValue* ScriptInterpreterPython::CastPyObjectToSBValue (void* data) { @@ -1811,7 +1844,8 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_ini SWIGPythonCalculateNumChildren python_swig_calc_children, SWIGPythonGetChildAtIndex python_swig_get_child_index, SWIGPythonGetIndexOfChildWithName python_swig_get_index_child, - SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue) + SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue, + SWIGPythonUpdateSynthProviderInstance python_swig_update_provider) { g_swig_init_callback = python_swig_init_callback; g_swig_breakpoint_callback = python_swig_breakpoint_callback; @@ -1821,6 +1855,7 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_ini g_swig_get_child_index = python_swig_get_child_index; g_swig_get_index_child = python_swig_get_index_child; g_swig_cast_to_sbvalue = python_swig_cast_to_sbvalue; + g_swig_update_provider = python_swig_update_provider; } void diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 7a204255ac3..52e07ce4fe7 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -66,8 +66,8 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, if (original_ptr == LLDB_INVALID_ADDRESS) return false; - Target *target = in_value.GetUpdatePoint().GetTarget(); - Process *process = in_value.GetUpdatePoint().GetProcess(); + Target *target = in_value.GetUpdatePoint().GetTargetSP().get(); + Process *process = in_value.GetUpdatePoint().GetProcessSP().get(); char memory_buffer[16]; DataExtractor data(memory_buffer, sizeof(memory_buffer), diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 80c548bccd2..9f2a93c9e06 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -235,7 +235,7 @@ AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value, Address &address) { // The Runtime is attached to a particular process, you shouldn't pass in a value from another process. - assert (in_value.GetUpdatePoint().GetProcess() == m_process); + assert (in_value.GetUpdatePoint().GetProcessSP().get() == m_process); // Make sure we can have a dynamic value before starting... if (CouldHaveDynamicValue (in_value)) diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index f99270a5143..e788d2e64c4 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -2725,7 +2725,7 @@ ClangASTContext::GetChildClangTypeAtIndex ObjCLanguageRuntime *objc_runtime = exe_ctx->process->GetObjCLanguageRuntime(); if (objc_runtime != NULL) { - ClangASTType parent_ast_type (parent_qual_type.getAsOpaquePtr(), ast); + ClangASTType parent_ast_type (ast, parent_qual_type.getAsOpaquePtr()); child_byte_offset = objc_runtime->GetByteOffsetForIvar (parent_ast_type, ivar_decl->getNameAsString().c_str()); } } diff --git a/lldb/source/Symbol/ClangASTType.cpp b/lldb/source/Symbol/ClangASTType.cpp index 9f885f936b1..3b24140607d 100644 --- a/lldb/source/Symbol/ClangASTType.cpp +++ b/lldb/source/Symbol/ClangASTType.cpp @@ -63,7 +63,7 @@ ClangASTType::GetTypeNameForQualType (clang::QualType qual_type) } // There is no call to a clang type to get the type name without the - // class/struct/union on the front, so lets strip it here + // class/struct/union/enum on the front, so lets strip it here const char *type_name_cstr = type_name.c_str(); if (type_name_cstr[0] == 'c' && type_name_cstr[1] == 'l' && @@ -93,6 +93,15 @@ ClangASTType::GetTypeNameForQualType (clang::QualType qual_type) { type_name.erase (0, 6); } + else if (type_name_cstr[0] == 'e' && + type_name_cstr[1] == 'n' && + type_name_cstr[2] == 'u' && + type_name_cstr[3] == 'm' && + type_name_cstr[4] == ' ') + { + type_name.erase (0, 5); + } + return type_name; } @@ -943,8 +952,11 @@ ClangASTType::GetClangTypeBitWidth () uint32_t ClangASTType::GetClangTypeBitWidth (clang::ASTContext *ast_context, clang_type_t clang_type) { - if (ast_context && clang_type) - return ast_context->getTypeSize(clang::QualType::getFromOpaquePtr(clang_type)); + if (ClangASTContext::GetCompleteType (ast_context, clang_type)) + { + clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type)); + return ast_context->getTypeSize (qual_type); + } return 0; } @@ -957,7 +969,7 @@ ClangASTType::GetTypeBitAlign () size_t ClangASTType::GetTypeBitAlign (clang::ASTContext *ast_context, clang_type_t clang_type) { - if (ast_context && clang_type) + if (ClangASTContext::GetCompleteType (ast_context, clang_type)) return ast_context->getTypeAlign(clang::QualType::getFromOpaquePtr(clang_type)); return 0; } @@ -1362,7 +1374,7 @@ ClangASTType::ReadFromMemory } uint32_t -ClangASTType::GetTypeByteSize() +ClangASTType::GetTypeByteSize() const { return GetTypeByteSize(m_ast, m_type); @@ -1379,7 +1391,7 @@ ClangASTType::GetTypeByteSize( clang::QualType qual_type(clang::QualType::getFromOpaquePtr(opaque_clang_qual_type)); return (ast_context->getTypeSize (qual_type) + 7) / 8; } - return UINT32_MAX; + return 0; } diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp index f9cd1015aba..1717118a5b6 100644 --- a/lldb/source/Symbol/Type.cpp +++ b/lldb/source/Symbol/Type.cpp @@ -730,3 +730,44 @@ TypeAndOrName::IsEmpty() else return true; } + +TypeImpl::TypeImpl(const lldb_private::ClangASTType& type) : +m_clang_ast_type(new ClangASTType(type.GetASTContext(), + type.GetOpaqueQualType())), +m_lldb_type(lldb::TypeSP()) +{} + +TypeImpl::TypeImpl(lldb::TypeSP type) : +m_clang_ast_type(new ClangASTType(type->GetClangAST(), + type->GetClangFullType())), +m_lldb_type(type) +{} + +TypeImpl& +TypeImpl::operator = (const TypeImpl& rhs) +{ + if (*this != rhs) + { + m_clang_ast_type = std::auto_ptr<ClangASTType>(rhs.m_clang_ast_type.get()); + m_lldb_type = lldb::TypeSP(rhs.m_lldb_type); + } + return *this; +} + +clang::ASTContext* +TypeImpl::GetASTContext() +{ + if (!IsValid()) + return NULL; + + return m_clang_ast_type->GetASTContext(); +} + +lldb::clang_type_t +TypeImpl::GetOpaqueQualType() +{ + if (!IsValid()) + return NULL; + + return m_clang_ast_type->GetOpaqueQualType(); +} diff --git a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdListSynthProvider.py b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdListSynthProvider.py new file mode 100644 index 00000000000..0f6ca4d5dd6 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdListSynthProvider.py @@ -0,0 +1,61 @@ +import re +class StdListSynthProvider: + def __init__(self, valobj, dict): + self.valobj = valobj; + self.update() + def num_children(self): + next_val = int(self.Mnext.GetValue(),0) + prev_val = int(self.Mprev.GetValue(),0) + if next_val == 0: + return 0; + if next_val == self.Mnode_address: + return 0; + if next_val == prev_val: + return 1; + size = 2 + current = self.Mnext + while int(current.GetChildMemberWithName('_M_next').GetValue(),0) != self.Mnode_address: + size = size + 1; + current = current.GetChildMemberWithName('_M_next') + return (size - 1) + def get_child_index(self,name): + if name == "len": + return self.num_children(); + else: + return int(name.lstrip('[').rstrip(']')) + def get_child_at_index(self,index): + if index == self.num_children(): + return self.valobj.CreateValueFromExpression("len",str(self.num_children())) + else: + offset = index + current = self.Mnext; + while offset > 0: + current = current.GetChildMemberWithName('_M_next'); + offset = offset - 1; + return current.CreateChildAtOffset('['+str(index)+']',2*current.GetType().GetByteSize(),self.data_type) + def extract_type_name(self,name): + self.type_name = name[16:] + index = 2 + count_of_template = 1 + while index < len(self.type_name): + if self.type_name[index] == '<': + count_of_template = count_of_template + 1; + elif self.type_name[index] == '>': + count_of_template = count_of_template - 1; + elif self.type_name[index] == ',' and count_of_template == 1: + self.type_name = self.type_name[:index] + break + index = index + 1; + self.type_name_nospaces = self.type_name.replace(", ", ",") + def update(self): + self.Mimpl = self.valobj.GetChildMemberWithName('_M_impl') + self.Mnode = self.Mimpl.GetChildMemberWithName('_M_node') + self.extract_type_name(self.Mimpl.GetType().GetName()) + self.Mnode_address = int(self.valobj.AddressOf().GetValue(), 0) + self.Mnext = self.Mnode.GetChildMemberWithName('_M_next') + self.Mprev = self.Mnode.GetChildMemberWithName('_M_prev') + self.data_type = self.Mnode.GetTarget().FindFirstType(self.type_name) + # tries to fight against a difference in formatting type names between gcc and clang + if self.data_type.IsValid() == False: + self.data_type = self.Mnode.GetTarget().FindFirstType(self.type_name_nospaces) + self.data_size = self.data_type.GetByteSize() diff --git a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdMapSynthProvider.py b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdMapSynthProvider.py new file mode 100644 index 00000000000..0665889896e --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdMapSynthProvider.py @@ -0,0 +1,103 @@ +import re +class StdMapSynthProvider: + def __init__(self, valobj, dict): + self.valobj = valobj; + self.update() + def update(self): + self.Mt = self.valobj.GetChildMemberWithName('_M_t') + self.Mimpl = self.Mt.GetChildMemberWithName('_M_impl') + self.Mheader = self.Mimpl.GetChildMemberWithName('_M_header') + # from libstdc++ implementation of _M_root for rbtree + self.Mroot = self.Mheader.GetChildMemberWithName('_M_parent') + # the stuff into the tree is actually a std::pair<const key, value> + # life would be much easier if gcc had a coherent way to print out + # template names in debug info + self.expand_clang_type_name() + self.expand_gcc_type_name() + self.data_type = self.Mt.GetTarget().FindFirstType(self.clang_type_name) + if self.data_type.IsValid() == False: + self.data_type = self.Mt.GetTarget().FindFirstType(self.gcc_type_name) + self.data_size = self.data_type.GetByteSize() + self.skip_size = self.Mheader.GetType().GetByteSize() + def expand_clang_type_name(self): + type_name = self.Mimpl.GetType().GetName() + index = type_name.find("std::pair<") + type_name = type_name[index+5:] + index = 6 + template_count = 1 + while index < len(type_name): + if type_name[index] == '<': + template_count = template_count + 1 + elif type_name[index] == '>' and template_count == 1: + type_name = type_name[:index+1] + break + elif type_name[index] == '>': + template_count = template_count - 1 + index = index + 1; + self.clang_type_name = type_name + def expand_gcc_type_name(self): + type_name = self.Mt.GetType().GetName() + index = type_name.find("std::pair<") + type_name = type_name[index+5:] + index = 6 + template_count = 1 + while index < len(type_name): + if type_name[index] == '<': + template_count = template_count + 1 + elif type_name[index] == '>' and template_count == 1: + type_name = type_name[:index+1] + break + elif type_name[index] == '>': + template_count = template_count - 1 + elif type_name[index] == ' ' and template_count == 1 and type_name[index-1] == ',': + type_name = type_name[0:index] + type_name[index+1:] + index = index - 1 + index = index + 1; + self.gcc_type_name = type_name + def num_children(self): + root_ptr_val = self.node_ptr_value(self.Mroot) + if root_ptr_val == 0: + return 0; + return int(self.Mimpl.GetChildMemberWithName('_M_node_count').GetValue(), 0); + def get_child_index(self,name): + if name == "len": + return self.num_children(); + else: + return int(name.lstrip('[').rstrip(']')) + def get_child_at_index(self,index): + if index == self.num_children(): + return self.valobj.CreateValueFromExpression("len",str(self.num_children())) + else: + offset = index + current = self.left(self.Mheader); + while offset > 0: + current = self.increment_node(current) + offset = offset - 1; + # skip all the base stuff and get at the data + return current.CreateChildAtOffset('['+str(index)+']',self.skip_size,self.data_type) + # utility functions + def node_ptr_value(self,node): + return int(node.GetValue(),0); + def right(self,node): + return node.GetChildMemberWithName("_M_right"); + def left(self,node): + return node.GetChildMemberWithName("_M_left"); + def parent(self,node): + return node.GetChildMemberWithName("_M_parent"); + # from libstdc++ implementation of iterator for rbtree + def increment_node(self,node): + if self.node_ptr_value(self.right(node)) != 0: + x = self.right(node); + while self.node_ptr_value(self.left(x)) != 0: + x = self.left(x); + return x; + else: + x = node; + y = self.parent(x) + while(self.node_ptr_value(x) == self.node_ptr_value(self.right(y))): + x = y; + y = self.parent(y); + if self.node_ptr_value(self.right(x)) != self.node_ptr_value(y): + x = y; + return x; + diff --git a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdVectorSynthProvider.py b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdVectorSynthProvider.py new file mode 100644 index 00000000000..91e634a718a --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/StdVectorSynthProvider.py @@ -0,0 +1,25 @@ +class StdVectorSynthProvider: + def __init__(self, valobj, dict): + self.valobj = valobj; + self.update() + def num_children(self): + start_val = int(self.Mstart.GetValue(),0) + finish_val = int(self.Mfinish.GetValue(),0) + return (finish_val-start_val)/self.data_size + def get_child_index(self,name): + if name == "len": + return self.num_children(); + else: + return int(name.lstrip('[').rstrip(']')) + def get_child_at_index(self,index): + if index == self.num_children(): + return self.valobj.CreateValueFromExpression("len",str(self.num_children())) + else: + offset = index * self.data_size + return self.Mstart.CreateChildAtOffset('['+str(index)+']',offset,self.data_type) + def update(self): + self.Mimpl = self.valobj.GetChildMemberWithName('_M_impl') + self.Mstart = self.Mimpl.GetChildMemberWithName('_M_start') + self.Mfinish = self.Mimpl.GetChildMemberWithName('_M_finish') + self.data_type = self.Mstart.GetType().GetPointeeType() + self.data_size = self.data_type.GetByteSize() diff --git a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py index 59f02086cc5..14859e0caef 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py @@ -64,9 +64,10 @@ class DataFormatterTestCase(TestBase): self.runCmd("script from fooSynthProvider import *") self.runCmd("type synth add -l fooSynthProvider foo") - # check that we get only the two variables + # check that we get the two real vars and the fake_a variables self.expect("frame variable f00_1", substrs = ['r = 33', + 'fake_a = 16777216', 'a = 0']); # check that we do not get the extra vars and that we cache results @@ -79,15 +80,389 @@ class DataFormatterTestCase(TestBase): self.expect("frame variable f00_1", substrs = ['r = 33', + 'fake_a = 16777216', 'a = 1']); + # check that altering the object also alters fake_a + self.runCmd("expr f00_1.a = 280") + self.expect("frame variable f00_1", + substrs = ['r = 33', + 'fake_a = 16777217', + 'a = 280']); + + # check that expanding a pointer does the right thing + self.expect("frame variable -P 1 f00_ptr", + substrs = ['r = 45', + 'fake_a = 218103808', + 'a = 12']) + # delete the synth and check that we get good output self.runCmd("type synth delete foo") self.expect("frame variable f00_1", - substrs = ['a = 1', + substrs = ['a = 280', 'b = 1', 'r = 33']); + self.expect("frame variable f00_1", matching=False, + substrs = ['fake_a = ']) + + self.runCmd("n") + + self.runCmd("script from ftsp import *") + self.runCmd("type synth add -l ftsp wrapint") + + self.expect('frame variable test_cast', + substrs = ['A', + 'B', + 'C', + 'D']) + + # now start playing with STL containers + # having std::<class_type> here is a workaround for rdar://problem/9835692 + + + # std::vector + self.runCmd("script from StdVectorSynthProvider import *") + self.runCmd("type synth add -l StdVectorSynthProvider std::int_vect int_vect") + self.runCmd("type synth add -l StdVectorSynthProvider std::string_vect string_vect") + + self.runCmd("n") + + # empty vectors (and storage pointers SHOULD BOTH BE NULL..) + self.expect("frame variable numbers", + substrs = ['numbers = {}']) + + self.runCmd("n") + + # first value added + self.expect("frame variable numbers", + substrs = ['numbers = {', + '[0] = 1', + '}']) + + # add some more data + self.runCmd("n");self.runCmd("n");self.runCmd("n"); + + self.expect("frame variable numbers", + substrs = ['numbers = {', + '[0] = 1', + '[1] = 12', + '[2] = 123', + '[3] = 1234', + '}']) + + # add some more data + self.runCmd("n");self.runCmd("n");self.runCmd("n"); + + self.expect("frame variable numbers", + substrs = ['numbers = {', + '[0] = 1', + '[1] = 12', + '[2] = 123', + '[3] = 1234', + '[4] = 12345', + '[5] = 123456', + '[6] = 1234567', + '}']) + + # clear out the vector and see that we do the right thing once again + self.runCmd("n") + + self.expect("frame variable numbers", + substrs = ['numbers = {}']) + + self.runCmd("n") + + # first value added + self.expect("frame variable numbers", + substrs = ['numbers = {', + '[0] = 7', + '}']) + + # check if we can display strings + self.runCmd("n") + self.runCmd("n") + self.runCmd("n") + self.runCmd("n") + + self.expect("frame variable strings", + substrs = ['goofy', + 'is', + 'smart']) + + # test summaries based on synthetic children + self.runCmd("type summary add std::string_vect string_vect -f \"vector has ${svar.len} items\" -e") + self.expect("frame variable strings", + substrs = ['vector has 3 items', + 'goofy', + 'is', + 'smart']) + + self.runCmd("n"); + + self.expect("frame variable strings", + substrs = ['vector has 4 items']) + + self.runCmd("n") + + self.expect("frame variable strings", + substrs = ['vector has 0 items']) + + # now test std::list + self.runCmd("script from StdListSynthProvider import *") + + self.runCmd("n") + + self.runCmd("frame variable numbers_list -T") + self.runCmd("type synth add std::int_list std::string_list int_list string_list -l StdListSynthProvider") + self.runCmd("type summary add std::int_list std::string_list int_list string_list -f \"list has ${svar.len} items\" -e") + self.runCmd("type format add -f hex int") + + self.expect("frame variable numbers_list", + substrs = ['list has 0x00000000 items', + '{}']) + + self.runCmd("n") + + self.expect("frame variable numbers_list", + substrs = ['list has 0x00000001 items', + '[0] = ', + '0x12345678']) + + self.runCmd("n");self.runCmd("n");self.runCmd("n"); + + self.expect("frame variable numbers_list", + substrs = ['list has 0x00000004 items', + '[0] = ', + '0x12345678', + '[1] =', + '0x11223344', + '[2] =', + '0xbeeffeed', + '[3] =', + '0x00abba00']) + + self.runCmd("n");self.runCmd("n"); + + self.expect("frame variable numbers_list", + substrs = ['list has 0x00000006 items', + '[0] = ', + '0x12345678', + '0x11223344', + '0xbeeffeed', + '0x00abba00', + '[4] =', + '0x0abcdef0', + '[5] =', + '0x0cab0cab']) + + self.runCmd("n") + + self.expect("frame variable numbers_list", + substrs = ['list has 0x00000000 items', + '{}']) + + + self.runCmd("n");self.runCmd("n");self.runCmd("n");self.runCmd("n"); + + self.expect("frame variable numbers_list", + substrs = ['list has 0x00000004 items', + '[0] = ', '1', + '[1] = ', '2', + '[2] = ', '3', + '[3] = ', '4']) + + self.runCmd("type format delete int") + + self.runCmd("n") + + self.expect("frame variable text_list", + substrs = ['list has 0 items', + '{}']) + + self.runCmd("n");self.runCmd("n");self.runCmd("n");self.runCmd("n"); + + self.expect("frame variable text_list", + substrs = ['list has 4 items', + '[0]', 'goofy', + '[1]', 'is', + '[2]', 'smart', + '[3]', '!!!']) + + # let's prettify string display + self.runCmd("type summary add -f \"${var._M_dataplus._M_p}\" std::string std::basic_string<char> \"std::basic_string<char,std::char_traits<char>,std::allocator<char> >\"") + + self.expect("frame variable text_list", + substrs = ['list has 4 items', + '[0] = \"goofy\"', + '[1] = \"is\"', + '[2] = \"smart\"', + '[3] = \"!!!\"']) + + # now std::map<K,V> + + self.runCmd("n") + self.runCmd("frame variable ii -T") + + self.runCmd("script from StdMapSynthProvider import *") + self.runCmd("type summary add std::intint_map intint_map -f \"map has ${svar.len} items\" -e") + self.runCmd("type synth add std::intint_map intint_map -l StdMapSynthProvider") + + + self.expect('frame variable ii', + substrs = ['map has 0 items', + '{}']) + + self.runCmd("n");self.runCmd("n"); + + self.expect('frame variable ii', + substrs = ['map has 2 items', + '[0] = {', + 'first = 0', + 'second = 0', + '[1] = {', + 'first = 1', + 'second = 1']) + + self.runCmd("n");self.runCmd("n"); + + self.expect('frame variable ii', + substrs = ['map has 4 items', + '[2] = {', + 'first = 2', + 'second = 0', + '[3] = {', + 'first = 3', + 'second = 1']) + + self.runCmd("n");self.runCmd("n"); + self.runCmd("n");self.runCmd("n");self.runCmd("n"); + + self.expect('frame variable ii', + substrs = ['map has 9 items', + '[5] = {', + 'first = 5', + 'second = 0', + '[7] = {', + 'first = 7', + 'second = 1']) + + self.runCmd("n") + + self.expect('frame variable ii', + substrs = ['map has 0 items', + '{}']) + + self.runCmd("n") + self.runCmd("frame variable si -T") + + self.runCmd("type summary add std::strint_map strint_map -f \"map has ${svar.len} items\" -e") + self.runCmd("type synth add std::strint_map strint_map -l StdMapSynthProvider") + + self.expect('frame variable si', + substrs = ['map has 0 items', + '{}']) + + self.runCmd("n") + + self.expect('frame variable si', + substrs = ['map has 1 items', + '[0] = ', + 'first = \"zero\"', + 'second = 0']) + + self.runCmd("n");self.runCmd("n");self.runCmd("n");self.runCmd("n"); + + self.expect('frame variable si', + substrs = ['map has 5 items', + '[0] = ', + 'first = \"zero\"', + 'second = 0', + '[1] = ', + 'first = \"one\"', + 'second = 1', + '[2] = ', + 'first = \"two\"', + 'second = 2', + '[3] = ', + 'first = \"three\"', + 'second = 3', + '[4] = ', + 'first = \"four\"', + 'second = 4']) + + self.runCmd("n") + + self.expect('frame variable si', + substrs = ['map has 0 items', + '{}']) + + self.runCmd("n") + self.runCmd("frame variable is -T") + + self.runCmd("type summary add std::intstr_map intstr_map -f \"map has ${svar.len} items\" -e") + self.runCmd("type synth add std::intstr_map intstr_map -l StdMapSynthProvider") + + self.expect('frame variable is', + substrs = ['map has 0 items', + '{}']) + + self.runCmd("n");self.runCmd("n");self.runCmd("n");self.runCmd("n"); + + self.expect('frame variable is', + substrs = ['map has 4 items', + '[0] = ', + 'second = \"goofy\"', + 'first = 0', + '[1] = ', + 'second = \"is\"', + 'first = 1', + '[2] = ', + 'second = \"smart\"', + 'first = 2', + '[3] = ', + 'second = \"!!!\"', + 'first = 3']) + + self.runCmd("n") + + self.expect('frame variable is', + substrs = ['map has 0 items', + '{}']) + + self.runCmd("n") + self.runCmd("frame variable ss -T") + + self.runCmd("type summary add std::strstr_map strstr_map -f \"map has ${svar.len} items\" -e") + self.runCmd("type synth add std::strstr_map strstr_map -l StdMapSynthProvider") + + self.expect('frame variable ss', + substrs = ['map has 0 items', + '{}']) + + self.runCmd("n");self.runCmd("n");self.runCmd("n");self.runCmd("n"); + + self.expect('frame variable ss', + substrs = ['map has 4 items', + '[0] = ', + 'second = \"hello\"', + 'first = \"ciao\"', + '[1] = ', + 'second = \"house\"', + 'first = \"casa\"', + '[2] = ', + 'second = \"cat\"', + 'first = \"gatto\"', + '[3] = ', + 'second = \"..is always a Mac!\"', + 'first = \"a Mac..\"']) + + self.runCmd("n") + + self.expect('frame variable ss', + substrs = ['map has 0 items', + '{}']) + if __name__ == '__main__': import atexit lldb.SBDebugger.Initialize() diff --git a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/fooSynthProvider.py b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/fooSynthProvider.py index 2d953265c6b..fb95ac2b54d 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/fooSynthProvider.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/fooSynthProvider.py @@ -1,16 +1,21 @@ +import lldb class fooSynthProvider: def __init__(self, valobj, dict): self.valobj = valobj; + self.int_type = valobj.GetType().GetBasicType(lldb.eBasicTypeInt) def num_children(self): - return 2; + return 3; def get_child_at_index(self, index): - if index == 1: + if index == 0: child = self.valobj.GetChildMemberWithName('a'); - else: + if index == 1: + child = self.valobj.CreateChildAtOffset ('fake_a', 1, self.int_type); + if index == 2: child = self.valobj.GetChildMemberWithName('r'); return child; def get_child_index(self, name): if name == 'a': - return 1; - else: return 0; + if name == 'fake_a': + return 1; + return 2; diff --git a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/ftsp.py b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/ftsp.py new file mode 100644 index 00000000000..f618672deaa --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/ftsp.py @@ -0,0 +1,20 @@ +import lldb +class ftsp: + def __init__(self, valobj, dict): + self.valobj = valobj; + self.update() + def num_children(self): + if self.char.IsValid(): + return 4; + return 0; + def get_child_index(self,name): + return 0; + def get_child_at_index(self,index): + if index == 0: + return self.x.Cast(self.char) + return self.x.CreateChildAtOffset(str(index), + index, + self.char); + def update(self): + self.x = self.valobj.GetChildMemberWithName('x'); + self.char = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar) diff --git a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/main.cpp b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/main.cpp index b541aa0bf9c..9a189861d6f 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/main.cpp +++ b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/main.cpp @@ -1,3 +1,18 @@ +#include <list> +#include <map> +#include <string> +#include <vector> +typedef std::vector<int> int_vect; +typedef std::vector<std::string> string_vect; + +typedef std::list<int> int_list; +typedef std::list<std::string> string_list; + +typedef std::map<int, int> intint_map; +typedef std::map<std::string, int> strint_map; +typedef std::map<int, std::string> intstr_map; +typedef std::map<std::string, std::string> strstr_map; + struct foo { int a; @@ -40,14 +55,110 @@ struct foo r(X+33) {} }; +struct wrapint +{ + int x; + wrapint(int X) : x(X) {} +}; + int main() { foo f00_1(0); - foo f00_2(6); - foo *f00_3 = new foo(12); - foo& f00_4 = *(new foo(18)); + foo *f00_ptr = new foo(12); f00_1.a++; // Set break point at this line. + wrapint test_cast('A' + + 256*'B' + + 256*256*'C'+ + 256*256*256*'D'); + + int_vect numbers; + numbers.push_back(1); + numbers.push_back(12); + numbers.push_back(123); + numbers.push_back(1234); + numbers.push_back(12345); + numbers.push_back(123456); + numbers.push_back(1234567); + + numbers.clear(); + + numbers.push_back(7); + + string_vect strings; + strings.push_back(std::string("goofy")); + strings.push_back(std::string("is")); + strings.push_back(std::string("smart")); + + strings.push_back(std::string("!!!")); + + strings.clear(); + + int_list numbers_list; + + numbers_list.push_back(0x12345678); + numbers_list.push_back(0x11223344); + numbers_list.push_back(0xBEEFFEED); + numbers_list.push_back(0x00ABBA00); + numbers_list.push_back(0x0ABCDEF0); + numbers_list.push_back(0x0CAB0CAB); + + numbers_list.clear(); + + numbers_list.push_back(1); + numbers_list.push_back(2); + numbers_list.push_back(3); + numbers_list.push_back(4); + + string_list text_list; + text_list.push_back(std::string("goofy")); + text_list.push_back(std::string("is")); + text_list.push_back(std::string("smart")); + + text_list.push_back(std::string("!!!")); + + intint_map ii; + + ii[0] = 0; + ii[1] = 1; + ii[2] = 0; + ii[3] = 1; + ii[4] = 0; + ii[5] = 1; + ii[6] = 0; + ii[7] = 1; + ii[8] = 0; + + ii.clear(); + + strint_map si; + + si["zero"] = 0; + si["one"] = 1; + si["two"] = 2; + si["three"] = 3; + si["four"] = 4; + + si.clear(); + + intstr_map is; + + is[0] = "goofy"; + is[1] = "is"; + is[2] = "smart"; + is[3] = "!!!"; + + is.clear(); + + strstr_map ss; + + ss["ciao"] = "hello"; + ss["casa"] = "house"; + ss["gatto"] = "cat"; + ss["a Mac.."] = "..is always a Mac!"; + + ss.clear(); + return 0; }
\ No newline at end of file diff --git a/lldb/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py b/lldb/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py index 622aba0f54f..23c96c3f187 100644 --- a/lldb/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py +++ b/lldb/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py @@ -294,6 +294,7 @@ class APIDefaultConstructorTestCase(TestBase): sb_thread.fuzz_obj(obj) @python_api_test + @unittest2.expectedFailure def test_SBType(self): obj = lldb.SBType() if self.TraceOn(): @@ -304,6 +305,7 @@ class APIDefaultConstructorTestCase(TestBase): sb_type.fuzz_obj(obj) @python_api_test + @unittest2.expectedFailure def test_SBTypeMember(self): obj = lldb.SBTypeMember() if self.TraceOn(): |