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
This commit is contained in:
Enrico Granata 2011-07-29 19:53:35 +00:00
parent ce0ceebb1c
commit 6f3533fb1d
53 changed files with 2291 additions and 614 deletions

View File

@ -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()

View File

@ -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;

View File

@ -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()

View File

@ -56,6 +56,8 @@ class SBSymbolContext;
class SBSymbolContextList;
class SBTarget;
class SBThread;
class SBType;
class SBTypeList;
class SBValue;
class SBValueList;

View File

@ -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;

View File

@ -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

View File

@ -11,129 +11,110 @@
#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);
const lldb::SBType &
operator = (const lldb::SBType &rhs);
bool
operator == (const lldb::SBType &rhs) const;
bool
operator != (const lldb::SBType &rhs) const;
lldb_private::TypeImpl &
ref ();
const lldb_private::TypeImpl &
ref () const;
#endif
bool
IsValid() const;
size_t
GetByteSize() const;
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);
IsPointerType() const;
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 ();
IsReferenceType() const;
SBType
GetPointeeType ();
static bool
IsPointerType (void *opaque_type);
bool
GetDescription (lldb::SBStream &description);
GetPointerType() const;
SBType
GetPointeeType() const;
SBType
GetReferenceType() const;
SBType
GetDereferencedType() const;
SBType
GetBasicType(lldb::BasicType type) const;
const char*
GetName();
protected:
void *m_ast;
void *m_type;
std::auto_ptr<lldb_private::TypeImpl> m_opaque_ap;
friend class SBModule;
friend class SBTarget;
friend class SBValue;
friend class SBTypeList;
SBType (clang::ASTContext*, clang_type_t);
SBType (lldb_private::ClangASTType type);
SBType (lldb::TypeSP type);
SBType (lldb_private::TypeImpl impl);
SBType();
};
class SBTypeMember
class SBTypeList
{
public:
SBTypeMember ();
SBTypeList();
SBTypeList(const SBTypeList& rhs);
SBTypeList&
operator = (const SBTypeList& rhs);
SBTypeMember (const SBTypeMember &rhs);
#ifndef SWIG
const SBTypeMember&
operator =(const SBTypeMember &rhs);
#endif
~SBTypeMember ();
bool
IsBaseClass ();
bool
IsValid ();
void
Clear();
bool
IsBitfield ();
AppendType(SBType type);
size_t
GetBitfieldWidth ();
SBType
GetTypeAtIndex(int index) const;
size_t
GetBitfieldOffset ();
size_t
GetOffset ();
const char *
GetName ();
SBType
GetType();
SBType
GetParentType();
void
SetName (const char *name);
protected:
friend class SBType;
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;
int
GetSize() const;
~SBTypeList();
private:
std::auto_ptr<lldb_private::TypeListImpl> m_opaque_ap;
};
} // namespace lldb
#endif // LLDB_SBType_h_

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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);
};

View File

@ -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

View File

@ -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;
@ -805,12 +809,6 @@ protected:
virtual uint32_t
CalculateNumChildren() = 0;
void
SetName (const char *name);
void
SetName (const ConstString &name);
void
SetNumChildren (uint32_t num_children);
@ -824,6 +822,10 @@ protected:
ClearUserVisibleData();
public:
void
SetName (const ConstString &name);
lldb::addr_t
GetPointerValue (AddressType &address_type,
bool scalar_is_load_address);

View File

@ -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 ();

View File

@ -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:

View File

@ -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,

View File

@ -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) { }

View File

@ -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_

View File

@ -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

View File

@ -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", "
//------------------------------------------------------------------

View File

@ -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", "
//------------------------------------------------------------------

View File

@ -9,91 +9,63 @@
namespace lldb {
class SBTypeMember;
class SBType
{
public:
SBType (void *ast = NULL, void *clang_type = NULL);
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();
};
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 ();
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

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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;
SBType::SBType (lldb_private::ClangASTType type) :
m_opaque_ap(new TypeImpl(ClangASTType(type.GetASTContext(),
type.GetOpaqueQualType())))
{
}
SBType::SBType (lldb::TypeSP type) :
m_opaque_ap(new TypeImpl(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 (clang::ASTContext *ctx, clang_type_t ty) :
m_opaque_ap(new TypeImpl(ClangASTType(ctx, ty)))
{
}
SBType::SBType() :
m_opaque_ap(NULL)
{
}
SBType::SBType (TypeImpl impl) :
m_opaque_ap(&impl)
{}
bool
SBType::IsPointerType (void *opaque_type)
SBType::operator == (const lldb::SBType &rhs) const
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
//if (log)
// log->Printf ("SBType::IsPointerType (%p)", opaque_type);
if (IsValid() == false)
return !rhs.IsValid();
bool ret_value = ClangASTContext::IsPointerType (opaque_type);
return (rhs.m_opaque_ap->GetASTContext() == m_opaque_ap->GetASTContext())
&&
(rhs.m_opaque_ap->GetOpaqueQualType() == m_opaque_ap->GetOpaqueQualType());
}
if (log)
log->Printf ("SBType::IsPointerType (opaque_type=%p) ==> '%s'", opaque_type, (ret_value ? "true" : "false"));
bool
SBType::operator != (const lldb::SBType &rhs) const
{
if (IsValid() == false)
return rhs.IsValid();
return ret_value;
return (rhs.m_opaque_ap->GetASTContext() != m_opaque_ap->GetASTContext())
||
(rhs.m_opaque_ap->GetOpaqueQualType() != m_opaque_ap->GetOpaqueQualType());
}
SBType::SBType (void *ast, void *clang_type) :
m_ast (ast),
m_type (clang_type)
const lldb::SBType &
SBType::operator = (const lldb::SBType &rhs)
{
}
SBType::SBType (const SBType &rhs) :
m_ast (rhs.m_ast),
m_type (rhs.m_type)
{
}
const SBType &
SBType::operator =(const SBType &rhs)
{
m_ast = rhs.m_ast;
m_type = rhs.m_type;
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;
}
SBType::~SBType ()
{}
lldb_private::TypeImpl &
SBType::ref ()
{
if (m_opaque_ap.get() == NULL)
m_opaque_ap.reset (new lldb_private::TypeImpl());
return *m_opaque_ap;
}
const lldb_private::TypeImpl &
SBType::ref () const
{
// "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::IsValid ()
SBType::IsValid() const
{
return m_ast != NULL && m_type != NULL;
}
const char *
SBType::GetName ()
{
if (IsValid ())
return ClangASTType::GetConstTypeName (m_type).AsCString(NULL);
return NULL;
}
uint64_t
SBType::GetByteSize()
{
if (IsValid ())
return ClangASTType::GetClangTypeBitWidth (static_cast<clang::ASTContext *>(m_ast), m_type);
return NULL;
}
Encoding
SBType::GetEncoding (uint32_t &count)
{
if (IsValid ())
return ClangASTType::GetEncoding (m_type, count);
count = 0;
return eEncodingInvalid;
}
uint64_t
SBType::GetNumberChildren (bool omit_empty_base_classes)
{
if (IsValid ())
return ClangASTContext::GetNumChildren (static_cast<clang::ASTContext *>(m_ast),
m_type,
omit_empty_base_classes);
return 0;
}
bool
SBType::GetChildAtIndex (bool omit_empty_base_classes, uint32_t idx, SBTypeMember &member)
{
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 ()
SBType::IsPointerType() const
{
return ClangASTContext::IsPointerType (m_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::IsReferenceType() const
{
if (!IsValid())
return false;
QualType qt = QualType::getFromOpaquePtr(m_opaque_ap->GetOpaqueQualType());
const clang::Type* typePtr = qt.getTypePtrOrNull();
if (typePtr)
return typePtr->isReferenceType();
return false;
}
SBType
SBType::GetPointeeType ()
SBType::GetPointerType() 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 SBType();
return SBType(m_opaque_ap->GetASTContext(),
ClangASTContext::CreatePointerType(m_opaque_ap->GetASTContext(), m_opaque_ap->GetOpaqueQualType()));
}
bool
SBType::GetDescription (SBStream &description)
SBType
SBType::GetPointeeType() const
{
const char *name = GetName();
uint64_t byte_size = GetByteSize();
uint64_t num_children = GetNumberChildren (true);
bool is_ptr = IsAPointerType ();
if (!IsValid())
return SBType();
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;
}
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 SBType(m_opaque_ap->GetASTContext(),typePtr->getPointeeType().getAsOpaquePtr());
return SBType();
}
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::GetReferenceType() const
{
if (!IsValid())
return SBType();
return SBType(m_opaque_ap->GetASTContext(),
ClangASTContext::CreateLValueReferenceType(m_opaque_ap->GetASTContext(), m_opaque_ap->GetOpaqueQualType()));
}
const SBTypeMember&
SBTypeMember::operator =(const SBTypeMember &rhs)
SBType
SBType::GetDereferencedType() const
{
if (this != &rhs)
if (!IsValid())
return SBType();
QualType qt = QualType::getFromOpaquePtr(m_opaque_ap->GetOpaqueQualType());
return SBType(m_opaque_ap->GetASTContext(),qt.getNonReferenceType().getAsOpaquePtr());
}
SBType
SBType::GetBasicType(lldb::BasicType type) const
{
if (!IsValid())
return SBType();
clang::CanQualType base_type_qual;
switch (type)
{
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;
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());
}
const char*
SBType::GetName()
{
if (!IsValid())
return "";
return ClangASTType::GetConstTypeName(m_opaque_ap->GetOpaqueQualType()).GetCString();
}
SBTypeList::SBTypeList() :
m_opaque_ap(new TypeListImpl())
{
}
SBTypeList::SBTypeList(const SBTypeList& rhs) :
m_opaque_ap(new TypeListImpl())
{
for (int j = 0; j < rhs.GetSize(); j++)
AppendType(rhs.GetTypeAtIndex(j));
}
SBTypeList&
SBTypeList::operator = (const SBTypeList& rhs)
{
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;
}
SBTypeMember::~SBTypeMember ()
{
SetName (NULL);
}
void
SBTypeMember::SetName (const char *name)
SBTypeList::AppendType(SBType type)
{
if (m_member_name)
free (m_member_name);
if (name && name[0])
m_member_name = ::strdup (name);
else
m_member_name = NULL;
}
void
SBTypeMember::Clear()
{
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;
}
bool
SBTypeMember::IsValid ()
{
return m_member_type != NULL;
}
bool
SBTypeMember::IsBitfield ()
{
return m_bit_size != 0;
}
size_t
SBTypeMember::GetBitfieldWidth ()
{
return m_bit_size;
}
size_t
SBTypeMember::GetBitfieldOffset ()
{
return m_bit_offset;
}
bool
SBTypeMember::IsBaseClass ()
{
return m_is_base_class;
}
size_t
SBTypeMember::GetOffset ()
{
return m_offset;
if (type.IsValid())
m_opaque_ap->AppendType(*type.m_opaque_ap.get());
}
SBType
SBTypeMember::GetType()
SBTypeList::GetTypeAtIndex(int index) const
{
return SBType (m_ast, m_member_type);
return SBType(m_opaque_ap->GetTypeAtIndex(index));
}
SBType
SBTypeMember::GetParentType()
int
SBTypeList::GetSize() const
{
return SBType (m_ast, m_parent_type);
return m_opaque_ap->GetSize();
}
const char *
SBTypeMember::GetName ()
SBTypeList::~SBTypeList()
{
return m_member_name;
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 }
};

View File

@ -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;

View File

@ -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;

View File

@ -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)
//{

View File

@ -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,

View File

@ -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();
@ -440,12 +446,6 @@ ValueObject::SetNumChildren (uint32_t num_children)
m_children.resize(num_children);
}
void
ValueObject::SetName (const char *name)
{
m_name.SetCString(name);
}
void
ValueObject::SetName (const ConstString &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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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),

View File

@ -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))

View File

@ -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());
}
}

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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()

View File

@ -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;

View File

@ -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()

View File

@ -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()

View File

@ -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;

View File

@ -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)

View File

@ -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;
}

View File

@ -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():