forked from OSchip/llvm-project
<rdar://problem/4529976>
Adding data formatters for iterators for std::map and std::vector (both libc++ and libstdcpp) This does not include reverse iterators since they are both trickier (due to requirements the standard imposes on them) and much less useful llvm-svn: 175787
This commit is contained in:
parent
efbbbfd384
commit
ea2bc0fb1f
|
@ -992,7 +992,7 @@ public:
|
|||
bool
|
||||
IsCStringContainer (bool check_pointer = false);
|
||||
|
||||
void
|
||||
size_t
|
||||
ReadPointedString (Stream& s,
|
||||
Error& error,
|
||||
uint32_t max_length = 0,
|
||||
|
@ -1260,7 +1260,6 @@ 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_child_at_offset:1,
|
||||
m_is_getting_summary:1,
|
||||
m_did_calculate_complete_objc_class_type:1;
|
||||
|
|
|
@ -557,9 +557,101 @@ namespace lldb_private {
|
|||
};
|
||||
|
||||
SyntheticChildrenFrontEnd* LibstdcppVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
|
||||
{
|
||||
public:
|
||||
LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
|
||||
|
||||
virtual size_t
|
||||
CalculateNumChildren ();
|
||||
|
||||
virtual lldb::ValueObjectSP
|
||||
GetChildAtIndex (size_t idx);
|
||||
|
||||
virtual bool
|
||||
Update();
|
||||
|
||||
virtual bool
|
||||
MightHaveChildren ();
|
||||
|
||||
virtual size_t
|
||||
GetIndexOfChildWithName (const ConstString &name);
|
||||
|
||||
virtual
|
||||
~LibstdcppMapIteratorSyntheticFrontEnd ();
|
||||
private:
|
||||
ExecutionContextRef m_exe_ctx_ref;
|
||||
lldb::addr_t m_pair_address;
|
||||
ClangASTType m_pair_type;
|
||||
EvaluateExpressionOptions m_options;
|
||||
lldb::ValueObjectSP m_pair_sp;
|
||||
};
|
||||
|
||||
SyntheticChildrenFrontEnd* LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
|
||||
|
||||
class LibCxxMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
|
||||
{
|
||||
public:
|
||||
LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
|
||||
|
||||
virtual size_t
|
||||
CalculateNumChildren ();
|
||||
|
||||
virtual lldb::ValueObjectSP
|
||||
GetChildAtIndex (size_t idx);
|
||||
|
||||
virtual bool
|
||||
Update();
|
||||
|
||||
virtual bool
|
||||
MightHaveChildren ();
|
||||
|
||||
virtual size_t
|
||||
GetIndexOfChildWithName (const ConstString &name);
|
||||
|
||||
virtual
|
||||
~LibCxxMapIteratorSyntheticFrontEnd ();
|
||||
private:
|
||||
ValueObject *m_pair_ptr;
|
||||
};
|
||||
|
||||
SyntheticChildrenFrontEnd* LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
|
||||
|
||||
#endif
|
||||
class VectorIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
|
||||
{
|
||||
public:
|
||||
VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
|
||||
ConstString item_name);
|
||||
|
||||
virtual size_t
|
||||
CalculateNumChildren ();
|
||||
|
||||
virtual lldb::ValueObjectSP
|
||||
GetChildAtIndex (size_t idx);
|
||||
|
||||
virtual bool
|
||||
Update();
|
||||
|
||||
virtual bool
|
||||
MightHaveChildren ();
|
||||
|
||||
virtual size_t
|
||||
GetIndexOfChildWithName (const ConstString &name);
|
||||
|
||||
virtual
|
||||
~VectorIteratorSyntheticFrontEnd ();
|
||||
private:
|
||||
ExecutionContextRef m_exe_ctx_ref;
|
||||
ConstString m_item_name;
|
||||
lldb::ValueObjectSP m_item_sp;
|
||||
};
|
||||
|
||||
SyntheticChildrenFrontEnd* LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
|
||||
|
||||
SyntheticChildrenFrontEnd* LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
|
||||
|
||||
} // namespace formatters
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // liblldb_CXXFormatterFunctions_h_
|
||||
|
|
|
@ -273,6 +273,15 @@ namespace lldb_private {
|
|||
m_expression_paths()
|
||||
{
|
||||
}
|
||||
|
||||
TypeFilterImpl(const SyntheticChildren::Flags& flags,
|
||||
const std::initializer_list<const char*> items) :
|
||||
SyntheticChildren(flags),
|
||||
m_expression_paths()
|
||||
{
|
||||
for (auto path : items)
|
||||
AddExpressionPath (path);
|
||||
}
|
||||
|
||||
void
|
||||
AddExpressionPath (const char* path)
|
||||
|
@ -305,7 +314,7 @@ namespace lldb_private {
|
|||
}
|
||||
|
||||
void
|
||||
AddExpressionPath (std::string path)
|
||||
AddExpressionPath (const std::string& path)
|
||||
{
|
||||
bool need_add_dot = true;
|
||||
if (path[0] == '.' ||
|
||||
|
@ -320,7 +329,7 @@ namespace lldb_private {
|
|||
}
|
||||
|
||||
bool
|
||||
SetExpressionPathAtIndex (int i, std::string path)
|
||||
SetExpressionPathAtIndex (int i, const std::string& path)
|
||||
{
|
||||
if (i >= GetCount())
|
||||
return false;
|
||||
|
|
|
@ -551,6 +551,8 @@
|
|||
94CB257116B0A4270059775D /* TypeSummary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CB256E16B0A4260059775D /* TypeSummary.cpp */; };
|
||||
94CB257216B0A4270059775D /* TypeSynthetic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CB256F16B0A4270059775D /* TypeSynthetic.cpp */; };
|
||||
94CB257416B1D3880059775D /* FormatCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CB257316B1D3870059775D /* FormatCache.cpp */; };
|
||||
94D0B10C16D5535900EA9C70 /* LibCxx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D0B10A16D5535900EA9C70 /* LibCxx.cpp */; };
|
||||
94D0B10D16D5535900EA9C70 /* LibStdcpp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D0B10B16D5535900EA9C70 /* LibStdcpp.cpp */; };
|
||||
94D6A0AA16CEB55F00833B6E /* NSArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D6A0A716CEB55F00833B6E /* NSArray.cpp */; };
|
||||
94D6A0AB16CEB55F00833B6E /* NSDictionary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D6A0A816CEB55F00833B6E /* NSDictionary.cpp */; };
|
||||
94D6A0AC16CEB55F00833B6E /* NSSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D6A0A916CEB55F00833B6E /* NSSet.cpp */; };
|
||||
|
@ -1594,6 +1596,8 @@
|
|||
94CB256F16B0A4270059775D /* TypeSynthetic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeSynthetic.cpp; path = source/DataFormatters/TypeSynthetic.cpp; sourceTree = "<group>"; };
|
||||
94CB257316B1D3870059775D /* FormatCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatCache.cpp; path = source/DataFormatters/FormatCache.cpp; sourceTree = "<group>"; };
|
||||
94CB257516B1D3910059775D /* FormatCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FormatCache.h; path = include/lldb/DataFormatters/FormatCache.h; sourceTree = "<group>"; };
|
||||
94D0B10A16D5535900EA9C70 /* LibCxx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxx.cpp; path = source/DataFormatters/LibCxx.cpp; sourceTree = "<group>"; };
|
||||
94D0B10B16D5535900EA9C70 /* LibStdcpp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibStdcpp.cpp; path = source/DataFormatters/LibStdcpp.cpp; sourceTree = "<group>"; };
|
||||
94D6A0A716CEB55F00833B6E /* NSArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSArray.cpp; path = source/DataFormatters/NSArray.cpp; sourceTree = "<group>"; };
|
||||
94D6A0A816CEB55F00833B6E /* NSDictionary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSDictionary.cpp; path = source/DataFormatters/NSDictionary.cpp; sourceTree = "<group>"; };
|
||||
94D6A0A916CEB55F00833B6E /* NSSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSSet.cpp; path = source/DataFormatters/NSSet.cpp; sourceTree = "<group>"; };
|
||||
|
@ -3370,6 +3374,8 @@
|
|||
94CB256216B069800059775D /* FormatManager.h */,
|
||||
94CB255A16B069770059775D /* FormatManager.cpp */,
|
||||
94CB256316B069800059775D /* FormatNavigator.h */,
|
||||
94D0B10A16D5535900EA9C70 /* LibCxx.cpp */,
|
||||
94D0B10B16D5535900EA9C70 /* LibStdcpp.cpp */,
|
||||
94D6A0A716CEB55F00833B6E /* NSArray.cpp */,
|
||||
94D6A0A816CEB55F00833B6E /* NSDictionary.cpp */,
|
||||
94D6A0A916CEB55F00833B6E /* NSSet.cpp */,
|
||||
|
@ -3947,6 +3953,7 @@
|
|||
2689004B13353E0400698AC0 /* Section.cpp in Sources */,
|
||||
2689004C13353E0400698AC0 /* SourceManager.cpp in Sources */,
|
||||
2689004D13353E0400698AC0 /* State.cpp in Sources */,
|
||||
94D0B10D16D5535900EA9C70 /* LibStdcpp.cpp in Sources */,
|
||||
2689004E13353E0400698AC0 /* Stream.cpp in Sources */,
|
||||
2689004F13353E0400698AC0 /* StreamFile.cpp in Sources */,
|
||||
2689005013353E0400698AC0 /* StreamString.cpp in Sources */,
|
||||
|
@ -4039,6 +4046,7 @@
|
|||
268900C213353E5F00698AC0 /* DWARFDebugPubnamesSet.cpp in Sources */,
|
||||
268900C313353E5F00698AC0 /* DWARFDebugRanges.cpp in Sources */,
|
||||
268900C413353E5F00698AC0 /* DWARFDefines.cpp in Sources */,
|
||||
94D0B10C16D5535900EA9C70 /* LibCxx.cpp in Sources */,
|
||||
268900C513353E5F00698AC0 /* DWARFDIECollection.cpp in Sources */,
|
||||
268900C613353E5F00698AC0 /* DWARFFormValue.cpp in Sources */,
|
||||
268900C713353E5F00698AC0 /* DWARFLocationDescription.cpp in Sources */,
|
||||
|
|
|
@ -96,7 +96,6 @@ ValueObject::ValueObject (ValueObject &parent) :
|
|||
m_is_deref_of_parent (false),
|
||||
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_is_getting_summary(false),
|
||||
m_did_calculate_complete_objc_class_type(false)
|
||||
|
@ -141,7 +140,6 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope,
|
|||
m_is_deref_of_parent (false),
|
||||
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_is_getting_summary(false),
|
||||
m_did_calculate_complete_objc_class_type(false)
|
||||
|
@ -1040,7 +1038,7 @@ strlen_or_inf (const char* str,
|
|||
return len;
|
||||
}
|
||||
|
||||
void
|
||||
size_t
|
||||
ValueObject::ReadPointedString (Stream& s,
|
||||
Error& error,
|
||||
uint32_t max_length,
|
||||
|
@ -1053,6 +1051,9 @@ ValueObject::ReadPointedString (Stream& s,
|
|||
if (target && max_length == 0)
|
||||
max_length = target->GetMaximumSizeOfStringSummary();
|
||||
|
||||
size_t bytes_read = 0;
|
||||
size_t total_bytes_read = 0;
|
||||
|
||||
clang_type_t clang_type = GetClangType();
|
||||
clang_type_t elem_or_pointee_clang_type;
|
||||
const Flags type_flags (GetTypeInfo (&elem_or_pointee_clang_type));
|
||||
|
@ -1090,7 +1091,6 @@ ValueObject::ReadPointedString (Stream& s,
|
|||
{
|
||||
Address cstr_so_addr (cstr_address);
|
||||
DataExtractor data;
|
||||
size_t bytes_read = 0;
|
||||
if (cstr_len > 0 && honor_array)
|
||||
{
|
||||
// I am using GetPointeeData() here to abstract the fact that some ValueObjects are actually frozen pointers in the host
|
||||
|
@ -1099,6 +1099,7 @@ ValueObject::ReadPointedString (Stream& s,
|
|||
|
||||
if ((bytes_read = data.GetByteSize()) > 0)
|
||||
{
|
||||
total_bytes_read = bytes_read;
|
||||
s << '"';
|
||||
data.Dump (&s,
|
||||
0, // Start offset in "data"
|
||||
|
@ -1127,6 +1128,7 @@ ValueObject::ReadPointedString (Stream& s,
|
|||
// but the pointed-to data lives in the debuggee, and GetPointeeData() automatically takes care of this
|
||||
while ((bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0)
|
||||
{
|
||||
total_bytes_read += bytes_read;
|
||||
const char *cstr = data.PeekCStr(0);
|
||||
size_t len = strlen_or_inf (cstr, k_max_buf_size, k_max_buf_size+1);
|
||||
if (len > k_max_buf_size)
|
||||
|
@ -1183,6 +1185,7 @@ ValueObject::ReadPointedString (Stream& s,
|
|||
error.SetErrorString("impossible to read a string from this object");
|
||||
s << "<not a string object>";
|
||||
}
|
||||
return total_bytes_read;
|
||||
}
|
||||
|
||||
const char *
|
||||
|
@ -2107,9 +2110,9 @@ ValueObject::GetSyntheticExpressionPathChild(const char* expression, bool can_cr
|
|||
// Cache the value if we got one back...
|
||||
if (synthetic_child_sp.get())
|
||||
{
|
||||
// FIXME: this causes a "real" child to end up with its name changed to the contents of expression
|
||||
AddSyntheticChild(name_const_string, synthetic_child_sp.get());
|
||||
synthetic_child_sp->SetName(ConstString(SkipLeadingExpressionPathSeparators(expression)));
|
||||
synthetic_child_sp->m_is_expression_path_child = true;
|
||||
}
|
||||
}
|
||||
return synthetic_child_sp;
|
||||
|
@ -2336,8 +2339,8 @@ ValueObject::GetValueForExpressionPath(const char* expression,
|
|||
{
|
||||
|
||||
const char* dummy_first_unparsed;
|
||||
ExpressionPathScanEndReason dummy_reason_to_stop;
|
||||
ExpressionPathEndResultType dummy_final_value_type;
|
||||
ExpressionPathScanEndReason dummy_reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnknown;
|
||||
ExpressionPathEndResultType dummy_final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
|
||||
ExpressionPathAftermath dummy_final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
|
||||
|
||||
ValueObjectSP ret_val = GetValueForExpressionPath_Impl(expression,
|
||||
|
|
|
@ -550,10 +550,11 @@ lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stre
|
|||
if (!location_sp)
|
||||
return false;
|
||||
Error error;
|
||||
location_sp->ReadPointedString(stream,
|
||||
error,
|
||||
0, // max length is decided by the settings
|
||||
false); // do not honor array (terminates on first 0 byte even for a char[])
|
||||
if (location_sp->ReadPointedString(stream,
|
||||
error,
|
||||
0, // max length is decided by the settings
|
||||
false) == 0) // do not honor array (terminates on first 0 byte even for a char[])
|
||||
stream.Printf("\"\""); // if nothing was read, print an empty string
|
||||
return error.Success();
|
||||
}
|
||||
|
||||
|
@ -1073,320 +1074,70 @@ lldb_private::formatters::ExtractIndexFromString (const char* item_name)
|
|||
return idx;
|
||||
}
|
||||
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
|
||||
SyntheticChildrenFrontEnd(*valobj_sp.get()),
|
||||
m_exe_ctx_ref(),
|
||||
m_count(0),
|
||||
m_base_data_address(0),
|
||||
m_options()
|
||||
{
|
||||
if (valobj_sp)
|
||||
Update();
|
||||
m_options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true)
|
||||
.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
||||
{
|
||||
if (idx >= m_count)
|
||||
return ValueObjectSP();
|
||||
if (m_base_data_address == 0 || m_count == 0)
|
||||
return ValueObjectSP();
|
||||
size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
|
||||
size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
|
||||
lldb::addr_t byte_location = m_base_data_address + byte_idx;
|
||||
ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
|
||||
if (!process_sp)
|
||||
return ValueObjectSP();
|
||||
uint8_t byte = 0;
|
||||
uint8_t mask = 0;
|
||||
Error err;
|
||||
size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
|
||||
if (err.Fail() || bytes_read == 0)
|
||||
return ValueObjectSP();
|
||||
switch (bit_index)
|
||||
{
|
||||
case 0:
|
||||
mask = 1; break;
|
||||
case 1:
|
||||
mask = 2; break;
|
||||
case 2:
|
||||
mask = 4; break;
|
||||
case 3:
|
||||
mask = 8; break;
|
||||
case 4:
|
||||
mask = 16; break;
|
||||
case 5:
|
||||
mask = 32; break;
|
||||
case 6:
|
||||
mask = 64; break;
|
||||
case 7:
|
||||
mask = 128; break;
|
||||
default:
|
||||
return ValueObjectSP();
|
||||
}
|
||||
bool bit_set = ((byte & mask) != 0);
|
||||
Target& target(process_sp->GetTarget());
|
||||
ValueObjectSP retval_sp;
|
||||
if (bit_set)
|
||||
target.EvaluateExpression("(bool)true", NULL, retval_sp);
|
||||
else
|
||||
target.EvaluateExpression("(bool)false", NULL, retval_sp);
|
||||
StreamString name; name.Printf("[%zu]",idx);
|
||||
if (retval_sp)
|
||||
retval_sp->SetName(ConstString(name.GetData()));
|
||||
return retval_sp;
|
||||
}
|
||||
|
||||
/*(std::__1::vector<std::__1::allocator<bool> >) vBool = {
|
||||
__begin_ = 0x00000001001000e0
|
||||
__size_ = 56
|
||||
__cap_alloc_ = {
|
||||
std::__1::__libcpp_compressed_pair_imp<unsigned long, std::__1::allocator<unsigned long> > = {
|
||||
__first_ = 1
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
bool
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update()
|
||||
{
|
||||
ValueObjectSP valobj_sp = m_backend.GetSP();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
if (valobj_sp->IsDynamic())
|
||||
valobj_sp = valobj_sp->GetStaticValue();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
|
||||
ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true));
|
||||
if (!size_sp)
|
||||
return false;
|
||||
m_count = size_sp->GetValueAsUnsigned(0);
|
||||
if (!m_count)
|
||||
return true;
|
||||
ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true));
|
||||
if (!begin_sp)
|
||||
{
|
||||
m_count = 0;
|
||||
return false;
|
||||
}
|
||||
m_base_data_address = begin_sp->GetValueAsUnsigned(0);
|
||||
if (!m_base_data_address)
|
||||
{
|
||||
m_count = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
|
||||
{
|
||||
if (!m_count || !m_base_data_address)
|
||||
return UINT32_MAX;
|
||||
const char* item_name = name.GetCString();
|
||||
uint32_t idx = ExtractIndexFromString(item_name);
|
||||
if (idx < UINT32_MAX && idx >= CalculateNumChildren())
|
||||
return UINT32_MAX;
|
||||
return idx;
|
||||
}
|
||||
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd ()
|
||||
{}
|
||||
|
||||
SyntheticChildrenFrontEnd*
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
|
||||
{
|
||||
if (!valobj_sp)
|
||||
return NULL;
|
||||
return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp));
|
||||
}
|
||||
|
||||
lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::LibstdcppVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
|
||||
lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
|
||||
ConstString item_name) :
|
||||
SyntheticChildrenFrontEnd(*valobj_sp.get()),
|
||||
m_exe_ctx_ref(),
|
||||
m_count(0),
|
||||
m_base_data_address(0),
|
||||
m_options()
|
||||
m_item_name(item_name),
|
||||
m_item_sp()
|
||||
{
|
||||
if (valobj_sp)
|
||||
Update();
|
||||
m_options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true)
|
||||
.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
||||
{
|
||||
if (idx >= m_count)
|
||||
return ValueObjectSP();
|
||||
if (m_base_data_address == 0 || m_count == 0)
|
||||
return ValueObjectSP();
|
||||
size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
|
||||
size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
|
||||
lldb::addr_t byte_location = m_base_data_address + byte_idx;
|
||||
ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
|
||||
if (!process_sp)
|
||||
return ValueObjectSP();
|
||||
uint8_t byte = 0;
|
||||
uint8_t mask = 0;
|
||||
Error err;
|
||||
size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
|
||||
if (err.Fail() || bytes_read == 0)
|
||||
return ValueObjectSP();
|
||||
switch (bit_index)
|
||||
{
|
||||
case 0:
|
||||
mask = 1; break;
|
||||
case 1:
|
||||
mask = 2; break;
|
||||
case 2:
|
||||
mask = 4; break;
|
||||
case 3:
|
||||
mask = 8; break;
|
||||
case 4:
|
||||
mask = 16; break;
|
||||
case 5:
|
||||
mask = 32; break;
|
||||
case 6:
|
||||
mask = 64; break;
|
||||
case 7:
|
||||
mask = 128; break;
|
||||
default:
|
||||
return ValueObjectSP();
|
||||
}
|
||||
bool bit_set = ((byte & mask) != 0);
|
||||
Target& target(process_sp->GetTarget());
|
||||
ValueObjectSP retval_sp;
|
||||
if (bit_set)
|
||||
target.EvaluateExpression("(bool)true", NULL, retval_sp);
|
||||
else
|
||||
target.EvaluateExpression("(bool)false", NULL, retval_sp);
|
||||
StreamString name; name.Printf("[%zu]",idx);
|
||||
if (retval_sp)
|
||||
retval_sp->SetName(ConstString(name.GetData()));
|
||||
return retval_sp;
|
||||
}
|
||||
|
||||
/*((std::vector<std::allocator<bool> >) vBool = {
|
||||
(std::_Bvector_base<std::allocator<bool> >) std::_Bvector_base<std::allocator<bool> > = {
|
||||
(std::_Bvector_base<std::allocator<bool> >::_Bvector_impl) _M_impl = {
|
||||
(std::_Bit_iterator) _M_start = {
|
||||
(std::_Bit_iterator_base) std::_Bit_iterator_base = {
|
||||
(_Bit_type *) _M_p = 0x0016b160
|
||||
(unsigned int) _M_offset = 0
|
||||
}
|
||||
}
|
||||
(std::_Bit_iterator) _M_finish = {
|
||||
(std::_Bit_iterator_base) std::_Bit_iterator_base = {
|
||||
(_Bit_type *) _M_p = 0x0016b16c
|
||||
(unsigned int) _M_offset = 16
|
||||
}
|
||||
}
|
||||
(_Bit_type *) _M_end_of_storage = 0x0016b170
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
bool
|
||||
lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::Update()
|
||||
lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
|
||||
{
|
||||
ValueObjectSP valobj_sp = m_backend.GetSP();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
if (valobj_sp->IsDynamic())
|
||||
valobj_sp = valobj_sp->GetStaticValue();
|
||||
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
|
||||
ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
|
||||
if (!item_ptr)
|
||||
return false;
|
||||
if (item_ptr->GetValueAsUnsigned(0) == 0)
|
||||
return false;
|
||||
Error err;
|
||||
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
|
||||
|
||||
ValueObjectSP m_impl_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_impl"), true));
|
||||
if (!m_impl_sp)
|
||||
return false;
|
||||
|
||||
ValueObjectSP m_start_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_start"), true));
|
||||
ValueObjectSP m_finish_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_finish"), true));
|
||||
|
||||
ValueObjectSP start_p_sp, finish_p_sp, finish_offset_sp;
|
||||
|
||||
if (!m_start_sp || !m_finish_sp)
|
||||
return false;
|
||||
|
||||
start_p_sp = m_start_sp->GetChildMemberWithName(ConstString("_M_p"), true);
|
||||
finish_p_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_p"), true);
|
||||
finish_offset_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_offset"), true);
|
||||
|
||||
if (!start_p_sp || !finish_offset_sp || !finish_p_sp)
|
||||
return false;
|
||||
m_item_sp = ValueObject::CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, ClangASTType(item_ptr->GetClangAST(),ClangASTType::GetPointeeType(item_ptr->GetClangType())));
|
||||
if (err.Fail())
|
||||
m_item_sp.reset();
|
||||
return (m_item_sp.get() != NULL);
|
||||
}
|
||||
|
||||
m_base_data_address = start_p_sp->GetValueAsUnsigned(0);
|
||||
if (!m_base_data_address)
|
||||
return false;
|
||||
|
||||
lldb::addr_t end_data_address(finish_p_sp->GetValueAsUnsigned(0));
|
||||
if (!end_data_address)
|
||||
return false;
|
||||
|
||||
if (end_data_address < m_base_data_address)
|
||||
return false;
|
||||
else
|
||||
m_count = finish_offset_sp->GetValueAsUnsigned(0) + (end_data_address-m_base_data_address)*8;
|
||||
size_t
|
||||
lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
lldb::ValueObjectSP
|
||||
lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
||||
{
|
||||
if (idx == 0)
|
||||
return m_item_sp;
|
||||
return lldb::ValueObjectSP();
|
||||
}
|
||||
|
||||
bool
|
||||
lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::MightHaveChildren ()
|
||||
lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
|
||||
lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
|
||||
{
|
||||
if (!m_count || !m_base_data_address)
|
||||
return UINT32_MAX;
|
||||
const char* item_name = name.GetCString();
|
||||
uint32_t idx = ExtractIndexFromString(item_name);
|
||||
if (idx < UINT32_MAX && idx >= CalculateNumChildren())
|
||||
return UINT32_MAX;
|
||||
return idx;
|
||||
if (name == ConstString("item"))
|
||||
return 0;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::~LibstdcppVectorBoolSyntheticFrontEnd ()
|
||||
{}
|
||||
|
||||
SyntheticChildrenFrontEnd*
|
||||
lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
|
||||
lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
|
||||
{
|
||||
if (!valobj_sp)
|
||||
return NULL;
|
||||
return (new LibstdcppVectorBoolSyntheticFrontEnd(valobj_sp));
|
||||
}
|
||||
|
||||
template bool
|
||||
|
|
|
@ -443,12 +443,16 @@ static void
|
|||
AddStringSummary(TypeCategoryImpl::SharedPointer category_sp,
|
||||
const char* string,
|
||||
ConstString type_name,
|
||||
TypeSummaryImpl::Flags flags)
|
||||
TypeSummaryImpl::Flags flags,
|
||||
bool regex = false)
|
||||
{
|
||||
lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags,
|
||||
string));
|
||||
category_sp->GetSummaryNavigator()->Add(type_name,
|
||||
summary_sp);
|
||||
|
||||
if (regex)
|
||||
{}
|
||||
else
|
||||
category_sp->GetSummaryNavigator()->Add(type_name, summary_sp);
|
||||
}
|
||||
|
||||
#ifndef LLDB_DISABLE_PYTHON
|
||||
|
@ -456,7 +460,8 @@ static void
|
|||
AddScriptSummary(TypeCategoryImpl::SharedPointer category_sp,
|
||||
const char* funct_name,
|
||||
ConstString type_name,
|
||||
TypeSummaryImpl::Flags flags)
|
||||
TypeSummaryImpl::Flags flags,
|
||||
bool regex = false)
|
||||
{
|
||||
|
||||
std::string code(" ");
|
||||
|
@ -465,8 +470,10 @@ AddScriptSummary(TypeCategoryImpl::SharedPointer category_sp,
|
|||
lldb::TypeSummaryImplSP summary_sp(new ScriptSummaryFormat(flags,
|
||||
funct_name,
|
||||
code.c_str()));
|
||||
category_sp->GetSummaryNavigator()->Add(type_name,
|
||||
summary_sp);
|
||||
if (regex)
|
||||
{}
|
||||
else
|
||||
category_sp->GetSummaryNavigator()->Add(type_name, summary_sp);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -476,11 +483,14 @@ AddCXXSummary (TypeCategoryImpl::SharedPointer category_sp,
|
|||
CXXFunctionSummaryFormat::Callback funct,
|
||||
const char* description,
|
||||
ConstString type_name,
|
||||
TypeSummaryImpl::Flags flags)
|
||||
TypeSummaryImpl::Flags flags,
|
||||
bool regex = false)
|
||||
{
|
||||
lldb::TypeSummaryImplSP summary_sp(new CXXFunctionSummaryFormat(flags,funct,description));
|
||||
category_sp->GetSummaryNavigator()->Add(type_name,
|
||||
summary_sp);
|
||||
if (regex)
|
||||
{}
|
||||
else
|
||||
category_sp->GetSummaryNavigator()->Add(type_name, summary_sp);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -489,10 +499,14 @@ static void AddCXXSynthetic (TypeCategoryImpl::SharedPointer category_sp,
|
|||
CXXSyntheticChildren::CreateFrontEndCallback generator,
|
||||
const char* description,
|
||||
ConstString type_name,
|
||||
ScriptedSyntheticChildren::Flags flags)
|
||||
ScriptedSyntheticChildren::Flags flags,
|
||||
bool regex = false)
|
||||
{
|
||||
lldb::SyntheticChildrenSP synth_sp(new CXXSyntheticChildren(flags,description,generator));
|
||||
category_sp->GetSyntheticNavigator()->Add(type_name,synth_sp);
|
||||
if (regex)
|
||||
category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())), synth_sp);
|
||||
else
|
||||
category_sp->GetSyntheticNavigator()->Add(type_name,synth_sp);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -561,6 +575,10 @@ FormatManager::LoadLibStdcppFormatters()
|
|||
gnu_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::list<.+>(( )?&)?$")),
|
||||
TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
|
||||
"size=${svar%#}")));
|
||||
|
||||
AddCXXSynthetic(gnu_category_sp, lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true);
|
||||
|
||||
AddCXXSynthetic(gnu_category_sp, lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
|
||||
|
||||
gnu_category_sp->GetSummaryNavigator()->Add(ConstString("std::vector<std::allocator<bool> >"),
|
||||
TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
|
||||
|
@ -634,9 +652,13 @@ FormatManager::LoadLibcxxFormatters()
|
|||
libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::deque<.+>(( )?&)?$")),
|
||||
TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
|
||||
libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::shared_ptr<.+>(( )?&)?$")),
|
||||
TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "{${var.__ptr_%S}} (strong=${var.count} weak=${var.weak_count})")));
|
||||
TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "{${var.__ptr_%S}} (strong=${var.count} weak=${var.weak_count})}")));
|
||||
libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::weak_ptr<.+>(( )?&)?$")),
|
||||
TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "{${var.__ptr_%S}} (strong=${var.count} weak=${var.weak_count})")));
|
||||
TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "{${var.__ptr_%S}} (strong=${var.count} weak=${var.weak_count})}")));
|
||||
|
||||
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^std::__1::__wrap_iter<.+>$"), stl_synth_flags, true);
|
||||
|
||||
AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::__1::__map_iterator<.+>$"), stl_synth_flags, true);
|
||||
|
||||
// this summary prevails on the regex std::vector<> because we do exact matches before regex ones
|
||||
libcxx_category_sp->GetSummaryNavigator()->Add(ConstString("std::__1::vector<std::__1::allocator<bool> >"),
|
||||
|
@ -644,7 +666,7 @@ FormatManager::LoadLibcxxFormatters()
|
|||
|
||||
libcxx_category_sp->GetSyntheticNavigator()->Add(ConstString("std::__1::vector<std::__1::allocator<bool> >"),
|
||||
SyntheticChildrenSP(new CXXSyntheticChildren(stl_synth_flags,"libc++ std::vector<bool> synthetic children",lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator)));
|
||||
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,285 @@
|
|||
//===-- LibCxx.cpp ------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/DataFormatters/CXXFormatterFunctions.h"
|
||||
|
||||
#include "lldb/Core/DataBufferHeap.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Core/Stream.h"
|
||||
#include "lldb/Core/ValueObject.h"
|
||||
#include "lldb/Core/ValueObjectConstResult.h"
|
||||
#include "lldb/Host/Endian.h"
|
||||
#include "lldb/Symbol/ClangASTContext.h"
|
||||
#include "lldb/Target/ObjCLanguageRuntime.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
using namespace lldb_private::formatters;
|
||||
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
|
||||
SyntheticChildrenFrontEnd(*valobj_sp.get()),
|
||||
m_exe_ctx_ref(),
|
||||
m_count(0),
|
||||
m_base_data_address(0),
|
||||
m_options()
|
||||
{
|
||||
if (valobj_sp)
|
||||
Update();
|
||||
m_options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true)
|
||||
.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
||||
{
|
||||
if (idx >= m_count)
|
||||
return ValueObjectSP();
|
||||
if (m_base_data_address == 0 || m_count == 0)
|
||||
return ValueObjectSP();
|
||||
size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
|
||||
size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
|
||||
lldb::addr_t byte_location = m_base_data_address + byte_idx;
|
||||
ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
|
||||
if (!process_sp)
|
||||
return ValueObjectSP();
|
||||
uint8_t byte = 0;
|
||||
uint8_t mask = 0;
|
||||
Error err;
|
||||
size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
|
||||
if (err.Fail() || bytes_read == 0)
|
||||
return ValueObjectSP();
|
||||
switch (bit_index)
|
||||
{
|
||||
case 0:
|
||||
mask = 1; break;
|
||||
case 1:
|
||||
mask = 2; break;
|
||||
case 2:
|
||||
mask = 4; break;
|
||||
case 3:
|
||||
mask = 8; break;
|
||||
case 4:
|
||||
mask = 16; break;
|
||||
case 5:
|
||||
mask = 32; break;
|
||||
case 6:
|
||||
mask = 64; break;
|
||||
case 7:
|
||||
mask = 128; break;
|
||||
default:
|
||||
return ValueObjectSP();
|
||||
}
|
||||
bool bit_set = ((byte & mask) != 0);
|
||||
Target& target(process_sp->GetTarget());
|
||||
ValueObjectSP retval_sp;
|
||||
if (bit_set)
|
||||
target.EvaluateExpression("(bool)true", NULL, retval_sp);
|
||||
else
|
||||
target.EvaluateExpression("(bool)false", NULL, retval_sp);
|
||||
StreamString name; name.Printf("[%zu]",idx);
|
||||
if (retval_sp)
|
||||
retval_sp->SetName(ConstString(name.GetData()));
|
||||
return retval_sp;
|
||||
}
|
||||
|
||||
/*(std::__1::vector<std::__1::allocator<bool> >) vBool = {
|
||||
__begin_ = 0x00000001001000e0
|
||||
__size_ = 56
|
||||
__cap_alloc_ = {
|
||||
std::__1::__libcpp_compressed_pair_imp<unsigned long, std::__1::allocator<unsigned long> > = {
|
||||
__first_ = 1
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
bool
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update()
|
||||
{
|
||||
ValueObjectSP valobj_sp = m_backend.GetSP();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
|
||||
ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true));
|
||||
if (!size_sp)
|
||||
return false;
|
||||
m_count = size_sp->GetValueAsUnsigned(0);
|
||||
if (!m_count)
|
||||
return true;
|
||||
ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true));
|
||||
if (!begin_sp)
|
||||
{
|
||||
m_count = 0;
|
||||
return false;
|
||||
}
|
||||
m_base_data_address = begin_sp->GetValueAsUnsigned(0);
|
||||
if (!m_base_data_address)
|
||||
{
|
||||
m_count = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
|
||||
{
|
||||
if (!m_count || !m_base_data_address)
|
||||
return UINT32_MAX;
|
||||
const char* item_name = name.GetCString();
|
||||
uint32_t idx = ExtractIndexFromString(item_name);
|
||||
if (idx < UINT32_MAX && idx >= CalculateNumChildren())
|
||||
return UINT32_MAX;
|
||||
return idx;
|
||||
}
|
||||
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd ()
|
||||
{}
|
||||
|
||||
SyntheticChildrenFrontEnd*
|
||||
lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
|
||||
{
|
||||
if (!valobj_sp)
|
||||
return NULL;
|
||||
return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp));
|
||||
}
|
||||
|
||||
/*
|
||||
(lldb) fr var ibeg --raw --ptr-depth 1
|
||||
(std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::pair<int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, void *> *, long> >) ibeg = {
|
||||
__i_ = {
|
||||
__ptr_ = 0x0000000100103870 {
|
||||
std::__1::__tree_node_base<void *> = {
|
||||
std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = {
|
||||
__left_ = 0x0000000000000000
|
||||
}
|
||||
__right_ = 0x0000000000000000
|
||||
__parent_ = 0x00000001001038b0
|
||||
__is_black_ = true
|
||||
}
|
||||
__value_ = {
|
||||
first = 0
|
||||
second = { std::string }
|
||||
*/
|
||||
|
||||
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
|
||||
SyntheticChildrenFrontEnd(*valobj_sp.get()),
|
||||
m_pair_ptr()
|
||||
{
|
||||
if (valobj_sp)
|
||||
Update();
|
||||
}
|
||||
|
||||
bool
|
||||
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update()
|
||||
{
|
||||
ValueObjectSP valobj_sp = m_backend.GetSP();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
|
||||
TargetSP target_sp(valobj_sp->GetTargetSP());
|
||||
|
||||
if (!target_sp)
|
||||
return false;
|
||||
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
|
||||
// this must be a ValueObject* because it is a child of the ValueObject we are producing children for
|
||||
// it if were a ValueObjectSP, we would end up with a loop (iterator -> synthetic -> child -> parent == iterator)
|
||||
// and that would in turn leak memory by never allowing the ValueObjects to die and free their memory
|
||||
m_pair_ptr = valobj_sp->GetValueForExpressionPath(".__i_.__ptr_->__value_",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ValueObject::GetValueForExpressionPathOptions().DontCheckDotVsArrowSyntax().DontAllowSyntheticChildren(),
|
||||
NULL).get();
|
||||
|
||||
return (m_pair_ptr != NULL);
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::CalculateNumChildren ()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
||||
{
|
||||
if (!m_pair_ptr)
|
||||
return lldb::ValueObjectSP();
|
||||
return m_pair_ptr->GetChildAtIndex(idx, true);
|
||||
}
|
||||
|
||||
bool
|
||||
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::MightHaveChildren ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
|
||||
{
|
||||
if (name == ConstString("first"))
|
||||
return 0;
|
||||
if (name == ConstString("second"))
|
||||
return 1;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::~LibCxxMapIteratorSyntheticFrontEnd ()
|
||||
{
|
||||
// this will be deleted when its parent dies (since it's a child object)
|
||||
//delete m_pair_ptr;
|
||||
}
|
||||
|
||||
SyntheticChildrenFrontEnd*
|
||||
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
|
||||
{
|
||||
if (!valobj_sp)
|
||||
return NULL;
|
||||
return (new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp));
|
||||
}
|
||||
|
||||
/*
|
||||
(lldb) fr var ibeg --raw --ptr-depth 1 -T
|
||||
(std::__1::__wrap_iter<int *>) ibeg = {
|
||||
(std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 {
|
||||
(int) *__i = 1
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
SyntheticChildrenFrontEnd*
|
||||
lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
|
||||
{
|
||||
static ConstString g_item_name;
|
||||
if (!g_item_name)
|
||||
g_item_name.SetCString("__i");
|
||||
if (!valobj_sp)
|
||||
return NULL;
|
||||
return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name));
|
||||
}
|
|
@ -0,0 +1,331 @@
|
|||
//===-- LibStdcpp.cpp ---------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/DataFormatters/CXXFormatterFunctions.h"
|
||||
|
||||
#include "lldb/Core/DataBufferHeap.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Core/Stream.h"
|
||||
#include "lldb/Core/ValueObject.h"
|
||||
#include "lldb/Core/ValueObjectConstResult.h"
|
||||
#include "lldb/Host/Endian.h"
|
||||
#include "lldb/Symbol/ClangASTContext.h"
|
||||
#include "lldb/Target/ObjCLanguageRuntime.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
using namespace lldb_private::formatters;
|
||||
|
||||
lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::LibstdcppVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
|
||||
SyntheticChildrenFrontEnd(*valobj_sp.get()),
|
||||
m_exe_ctx_ref(),
|
||||
m_count(0),
|
||||
m_base_data_address(0),
|
||||
m_options()
|
||||
{
|
||||
if (valobj_sp)
|
||||
Update();
|
||||
m_options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true)
|
||||
.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
||||
{
|
||||
if (idx >= m_count)
|
||||
return ValueObjectSP();
|
||||
if (m_base_data_address == 0 || m_count == 0)
|
||||
return ValueObjectSP();
|
||||
size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
|
||||
size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
|
||||
lldb::addr_t byte_location = m_base_data_address + byte_idx;
|
||||
ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
|
||||
if (!process_sp)
|
||||
return ValueObjectSP();
|
||||
uint8_t byte = 0;
|
||||
uint8_t mask = 0;
|
||||
Error err;
|
||||
size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
|
||||
if (err.Fail() || bytes_read == 0)
|
||||
return ValueObjectSP();
|
||||
switch (bit_index)
|
||||
{
|
||||
case 0:
|
||||
mask = 1; break;
|
||||
case 1:
|
||||
mask = 2; break;
|
||||
case 2:
|
||||
mask = 4; break;
|
||||
case 3:
|
||||
mask = 8; break;
|
||||
case 4:
|
||||
mask = 16; break;
|
||||
case 5:
|
||||
mask = 32; break;
|
||||
case 6:
|
||||
mask = 64; break;
|
||||
case 7:
|
||||
mask = 128; break;
|
||||
default:
|
||||
return ValueObjectSP();
|
||||
}
|
||||
bool bit_set = ((byte & mask) != 0);
|
||||
Target& target(process_sp->GetTarget());
|
||||
ValueObjectSP retval_sp;
|
||||
if (bit_set)
|
||||
target.EvaluateExpression("(bool)true", NULL, retval_sp);
|
||||
else
|
||||
target.EvaluateExpression("(bool)false", NULL, retval_sp);
|
||||
StreamString name; name.Printf("[%zu]",idx);
|
||||
if (retval_sp)
|
||||
retval_sp->SetName(ConstString(name.GetData()));
|
||||
return retval_sp;
|
||||
}
|
||||
|
||||
/*((std::vector<std::allocator<bool> >) vBool = {
|
||||
(std::_Bvector_base<std::allocator<bool> >) std::_Bvector_base<std::allocator<bool> > = {
|
||||
(std::_Bvector_base<std::allocator<bool> >::_Bvector_impl) _M_impl = {
|
||||
(std::_Bit_iterator) _M_start = {
|
||||
(std::_Bit_iterator_base) std::_Bit_iterator_base = {
|
||||
(_Bit_type *) _M_p = 0x0016b160
|
||||
(unsigned int) _M_offset = 0
|
||||
}
|
||||
}
|
||||
(std::_Bit_iterator) _M_finish = {
|
||||
(std::_Bit_iterator_base) std::_Bit_iterator_base = {
|
||||
(_Bit_type *) _M_p = 0x0016b16c
|
||||
(unsigned int) _M_offset = 16
|
||||
}
|
||||
}
|
||||
(_Bit_type *) _M_end_of_storage = 0x0016b170
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
bool
|
||||
lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::Update()
|
||||
{
|
||||
ValueObjectSP valobj_sp = m_backend.GetSP();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
|
||||
|
||||
ValueObjectSP m_impl_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_impl"), true));
|
||||
if (!m_impl_sp)
|
||||
return false;
|
||||
|
||||
ValueObjectSP m_start_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_start"), true));
|
||||
ValueObjectSP m_finish_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_finish"), true));
|
||||
|
||||
ValueObjectSP start_p_sp, finish_p_sp, finish_offset_sp;
|
||||
|
||||
if (!m_start_sp || !m_finish_sp)
|
||||
return false;
|
||||
|
||||
start_p_sp = m_start_sp->GetChildMemberWithName(ConstString("_M_p"), true);
|
||||
finish_p_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_p"), true);
|
||||
finish_offset_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_offset"), true);
|
||||
|
||||
if (!start_p_sp || !finish_offset_sp || !finish_p_sp)
|
||||
return false;
|
||||
|
||||
m_base_data_address = start_p_sp->GetValueAsUnsigned(0);
|
||||
if (!m_base_data_address)
|
||||
return false;
|
||||
|
||||
lldb::addr_t end_data_address(finish_p_sp->GetValueAsUnsigned(0));
|
||||
if (!end_data_address)
|
||||
return false;
|
||||
|
||||
if (end_data_address < m_base_data_address)
|
||||
return false;
|
||||
else
|
||||
m_count = finish_offset_sp->GetValueAsUnsigned(0) + (end_data_address-m_base_data_address)*8;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::MightHaveChildren ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
|
||||
{
|
||||
if (!m_count || !m_base_data_address)
|
||||
return UINT32_MAX;
|
||||
const char* item_name = name.GetCString();
|
||||
uint32_t idx = ExtractIndexFromString(item_name);
|
||||
if (idx < UINT32_MAX && idx >= CalculateNumChildren())
|
||||
return UINT32_MAX;
|
||||
return idx;
|
||||
}
|
||||
|
||||
lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::~LibstdcppVectorBoolSyntheticFrontEnd ()
|
||||
{}
|
||||
|
||||
SyntheticChildrenFrontEnd*
|
||||
lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
|
||||
{
|
||||
if (!valobj_sp)
|
||||
return NULL;
|
||||
return (new LibstdcppVectorBoolSyntheticFrontEnd(valobj_sp));
|
||||
}
|
||||
|
||||
/*
|
||||
(std::_Rb_tree_iterator<std::pair<const int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >) ibeg = {
|
||||
(_Base_ptr) _M_node = 0x0000000100103910 {
|
||||
(std::_Rb_tree_color) _M_color = _S_black
|
||||
(std::_Rb_tree_node_base::_Base_ptr) _M_parent = 0x00000001001038c0
|
||||
(std::_Rb_tree_node_base::_Base_ptr) _M_left = 0x0000000000000000
|
||||
(std::_Rb_tree_node_base::_Base_ptr) _M_right = 0x0000000000000000
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
|
||||
SyntheticChildrenFrontEnd(*valobj_sp.get()),
|
||||
m_exe_ctx_ref(),
|
||||
m_pair_address(0),
|
||||
m_pair_type(),
|
||||
m_options(),
|
||||
m_pair_sp()
|
||||
{
|
||||
if (valobj_sp)
|
||||
Update();
|
||||
m_options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true)
|
||||
.SetUseDynamic(lldb::eDynamicCanRunTarget);
|
||||
}
|
||||
|
||||
bool
|
||||
lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::Update()
|
||||
{
|
||||
ValueObjectSP valobj_sp = m_backend.GetSP();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
|
||||
TargetSP target_sp(valobj_sp->GetTargetSP());
|
||||
|
||||
if (!target_sp)
|
||||
return false;
|
||||
|
||||
bool is_64bit = (target_sp->GetArchitecture().GetAddressByteSize() == 8);
|
||||
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
|
||||
|
||||
ValueObjectSP _M_node_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_node"), true));
|
||||
if (!_M_node_sp)
|
||||
return false;
|
||||
|
||||
m_pair_address = _M_node_sp->GetValueAsUnsigned(0);
|
||||
if (m_pair_address == 0)
|
||||
return false;
|
||||
|
||||
m_pair_address += (is_64bit ? 32 : 16);
|
||||
|
||||
ClangASTType my_type(valobj_sp->GetClangAST(),valobj_sp->GetClangType());
|
||||
if (ClangASTContext::GetNumTemplateArguments(valobj_sp->GetClangAST(),valobj_sp->GetClangType()) >= 1)
|
||||
{
|
||||
TemplateArgumentKind kind;
|
||||
clang_type_t pair_type = ClangASTContext::GetTemplateArgument(valobj_sp->GetClangAST(),valobj_sp->GetClangType(), 0, kind);
|
||||
if (kind != eTemplateArgumentKindType && kind != eTemplateArgumentKindTemplate && kind != eTemplateArgumentKindTemplateExpansion)
|
||||
return false;
|
||||
m_pair_type = ClangASTType(valobj_sp->GetClangAST(),pair_type);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::CalculateNumChildren ()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
lldb::ValueObjectSP
|
||||
lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
|
||||
{
|
||||
if (m_pair_address == 0)
|
||||
return lldb::ValueObjectSP();
|
||||
if (m_pair_type.GetASTContext() == NULL ||
|
||||
m_pair_type.GetOpaqueQualType() == NULL)
|
||||
return lldb::ValueObjectSP();
|
||||
if (!m_pair_sp)
|
||||
m_pair_sp = ValueObject::CreateValueObjectFromAddress("pair", m_pair_address, m_exe_ctx_ref, m_pair_type);
|
||||
if (m_pair_sp)
|
||||
return m_pair_sp->GetChildAtIndex(idx, true);
|
||||
return lldb::ValueObjectSP();
|
||||
}
|
||||
|
||||
bool
|
||||
lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::MightHaveChildren ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
|
||||
{
|
||||
if (name == ConstString("first"))
|
||||
return 0;
|
||||
if (name == ConstString("second"))
|
||||
return 1;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::~LibstdcppMapIteratorSyntheticFrontEnd ()
|
||||
{}
|
||||
|
||||
SyntheticChildrenFrontEnd*
|
||||
lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
|
||||
{
|
||||
if (!valobj_sp)
|
||||
return NULL;
|
||||
return (new LibstdcppMapIteratorSyntheticFrontEnd(valobj_sp));
|
||||
}
|
||||
|
||||
/*
|
||||
(lldb) fr var ibeg --ptr-depth 1
|
||||
(__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >) ibeg = {
|
||||
_M_current = 0x00000001001037a0 {
|
||||
*_M_current = 1
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
SyntheticChildrenFrontEnd*
|
||||
lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
|
||||
{
|
||||
static ConstString g_item_name;
|
||||
if (!g_item_name)
|
||||
g_item_name.SetCString("_M_current");
|
||||
if (!valobj_sp)
|
||||
return NULL;
|
||||
return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name));
|
||||
}
|
|
@ -7,12 +7,8 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/lldb-python.h"
|
||||
|
||||
#include "lldb/DataFormatters/CXXFormatterFunctions.h"
|
||||
|
||||
#include "llvm/Support/ConvertUTF.h"
|
||||
|
||||
#include "lldb/Core/DataBufferHeap.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Core/Stream.h"
|
||||
|
@ -144,8 +140,6 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::Update()
|
|||
m_data_32 = NULL;
|
||||
delete m_data_64;
|
||||
m_data_64 = NULL;
|
||||
if (valobj_sp->IsDynamic())
|
||||
valobj_sp = valobj_sp->GetStaticValue();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
|
||||
|
@ -245,8 +239,6 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd::Update()
|
|||
m_data_ptr = 0;
|
||||
m_children.clear();
|
||||
ValueObjectSP valobj_sp = m_backend.GetSP();
|
||||
if (valobj_sp->IsDynamic())
|
||||
valobj_sp = valobj_sp->GetStaticValue();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
|
||||
|
|
|
@ -7,12 +7,8 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/lldb-python.h"
|
||||
|
||||
#include "lldb/DataFormatters/CXXFormatterFunctions.h"
|
||||
|
||||
#include "llvm/Support/ConvertUTF.h"
|
||||
|
||||
#include "lldb/Core/DataBufferHeap.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Core/Stream.h"
|
||||
|
@ -245,8 +241,6 @@ lldb_private::formatters::NSDictionaryISyntheticFrontEnd::Update()
|
|||
ValueObjectSP valobj_sp = m_backend.GetSP();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
if (valobj_sp->IsDynamic())
|
||||
valobj_sp = valobj_sp->GetStaticValue();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
|
||||
|
@ -393,8 +387,6 @@ lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update()
|
|||
m_data_64 = NULL;
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
if (valobj_sp->IsDynamic())
|
||||
valobj_sp = valobj_sp->GetStaticValue();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
|
||||
|
|
|
@ -7,12 +7,8 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/lldb-python.h"
|
||||
|
||||
#include "lldb/DataFormatters/CXXFormatterFunctions.h"
|
||||
|
||||
#include "llvm/Support/ConvertUTF.h"
|
||||
|
||||
#include "lldb/Core/DataBufferHeap.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Core/Stream.h"
|
||||
|
@ -201,8 +197,6 @@ lldb_private::formatters::NSSetISyntheticFrontEnd::Update()
|
|||
ValueObjectSP valobj_sp = m_backend.GetSP();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
if (valobj_sp->IsDynamic())
|
||||
valobj_sp = valobj_sp->GetStaticValue();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
|
||||
|
@ -345,8 +339,6 @@ lldb_private::formatters::NSSetMSyntheticFrontEnd::Update()
|
|||
m_data_64 = NULL;
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
if (valobj_sp->IsDynamic())
|
||||
valobj_sp = valobj_sp->GetStaticValue();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
LEVEL = ../../../../../make
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
||||
|
||||
CXXFLAGS += -stdlib=libc++ -O0
|
||||
LDFLAGS += -stdlib=libc++
|
|
@ -0,0 +1,78 @@
|
|||
"""
|
||||
Test lldb data formatter subsystem.
|
||||
"""
|
||||
|
||||
import os, time
|
||||
import unittest2
|
||||
import lldb
|
||||
from lldbtest import *
|
||||
import lldbutil
|
||||
|
||||
class LibcxxIteratorDataFormatterTestCase(TestBase):
|
||||
|
||||
mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "libcxx", "iterator")
|
||||
|
||||
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
|
||||
@dsym_test
|
||||
def test_with_dsym_and_run_command(self):
|
||||
"""Test data formatter commands."""
|
||||
self.buildDsym()
|
||||
self.data_formatter_commands()
|
||||
|
||||
@skipOnLinux # No standard locations for libc++ on Linux, so skip for now
|
||||
@dwarf_test
|
||||
def test_with_dwarf_and_run_command(self):
|
||||
"""Test data formatter commands."""
|
||||
self.buildDwarf()
|
||||
self.data_formatter_commands()
|
||||
|
||||
def setUp(self):
|
||||
# Call super's setUp().
|
||||
TestBase.setUp(self)
|
||||
# Find the line number to break at.
|
||||
self.line = line_number('main.cpp', '// Set break point at this line.')
|
||||
|
||||
def data_formatter_commands(self):
|
||||
"""Test that libc++ iterators format properly."""
|
||||
self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
|
||||
|
||||
lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=-1)
|
||||
|
||||
self.runCmd("run", RUN_SUCCEEDED)
|
||||
|
||||
# The stop reason of the thread should be breakpoint.
|
||||
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
||||
substrs = ['stopped',
|
||||
'stop reason = breakpoint'])
|
||||
|
||||
# This is the function to remove the custom formats in order to have a
|
||||
# clean slate for the next test case.
|
||||
def cleanup():
|
||||
self.runCmd('type format clear', check=False)
|
||||
self.runCmd('type summary clear', check=False)
|
||||
self.runCmd('type filter clear', check=False)
|
||||
self.runCmd('type synth clear', check=False)
|
||||
self.runCmd("settings set target.max-children-count 256", check=False)
|
||||
|
||||
# Execute the cleanup function during test case tear down.
|
||||
self.addTearDownHook(cleanup)
|
||||
|
||||
self.expect('image list',substrs=['libc++.1.dylib','libc++abi.dylib'])
|
||||
|
||||
self.expect('frame variable ivI', substrs = ['item = 3'])
|
||||
self.expect('expr ivI', substrs = ['item = 3'])
|
||||
|
||||
self.expect('frame variable iimI', substrs = ['first = 0','second = 12'])
|
||||
self.expect('expr iimI', substrs = ['first = 0','second = 12'])
|
||||
|
||||
self.expect('frame variable simI', substrs = ['first = "world"','second = 42'])
|
||||
self.expect('expr simI', substrs = ['first = "world"','second = 42'])
|
||||
|
||||
self.expect('frame variable svI', substrs = ['item = "hello"'])
|
||||
self.expect('expr svI', substrs = ['item = "hello"'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
import atexit
|
||||
lldb.SBDebugger.Initialize()
|
||||
atexit.register(lambda: lldb.SBDebugger.Terminate())
|
||||
unittest2.main()
|
|
@ -0,0 +1,42 @@
|
|||
#include <string>
|
||||
#ifdef _LIBCPP_INLINE_VISIBILITY
|
||||
#undef _LIBCPP_INLINE_VISIBILITY
|
||||
#endif
|
||||
#define _LIBCPP_INLINE_VISIBILITY
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
typedef std::map<int, int> intint_map;
|
||||
typedef std::map<std::string, int> strint_map;
|
||||
|
||||
typedef std::vector<int> int_vector;
|
||||
typedef std::vector<std::string> string_vector;
|
||||
|
||||
typedef intint_map::iterator iimter;
|
||||
typedef strint_map::iterator simter;
|
||||
|
||||
typedef int_vector::iterator ivter;
|
||||
typedef string_vector::iterator svter;
|
||||
|
||||
int main()
|
||||
{
|
||||
intint_map iim;
|
||||
iim[0] = 12;
|
||||
|
||||
strint_map sim;
|
||||
sim["world"] = 42;
|
||||
|
||||
int_vector iv;
|
||||
iv.push_back(3);
|
||||
|
||||
string_vector sv;
|
||||
sv.push_back("hello");
|
||||
|
||||
iimter iimI = iim.begin();
|
||||
simter simI = sim.begin();
|
||||
|
||||
ivter ivI = iv.begin();
|
||||
svter svI = sv.begin();
|
||||
|
||||
return 0; // Set break point at this line.
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
LEVEL = ../../../../../make
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
||||
|
||||
CXXFLAGS += -stdlib=libstdc++ -O0
|
||||
LDFLAGS += -stdlib=libstdc++
|
|
@ -0,0 +1,76 @@
|
|||
"""
|
||||
Test lldb data formatter subsystem.
|
||||
"""
|
||||
|
||||
import os, time
|
||||
import unittest2
|
||||
import lldb
|
||||
from lldbtest import *
|
||||
import lldbutil
|
||||
|
||||
class StdIteratorDataFormatterTestCase(TestBase):
|
||||
|
||||
mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "libstdcpp", "iterator")
|
||||
|
||||
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
|
||||
@dsym_test
|
||||
def test_with_dsym_and_run_command(self):
|
||||
"""Test data formatter commands."""
|
||||
self.buildDsym()
|
||||
self.data_formatter_commands()
|
||||
|
||||
@skipOnLinux #PR-15256: assertion failure in RecordLayoutBuilder::updateExternalFieldOffset
|
||||
@dwarf_test
|
||||
def test_with_dwarf_and_run_command(self):
|
||||
"""Test data formatter commands."""
|
||||
self.buildDwarf()
|
||||
self.data_formatter_commands()
|
||||
|
||||
def setUp(self):
|
||||
# Call super's setUp().
|
||||
TestBase.setUp(self)
|
||||
# Find the line number to break at.
|
||||
self.line = line_number('main.cpp', '// Set break point at this line.')
|
||||
|
||||
def data_formatter_commands(self):
|
||||
"""Test that libstdcpp iterators format properly."""
|
||||
self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
|
||||
|
||||
lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=-1)
|
||||
|
||||
self.runCmd("run", RUN_SUCCEEDED)
|
||||
|
||||
# The stop reason of the thread should be breakpoint.
|
||||
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
||||
substrs = ['stopped',
|
||||
'stop reason = breakpoint'])
|
||||
|
||||
# This is the function to remove the custom formats in order to have a
|
||||
# clean slate for the next test case.
|
||||
def cleanup():
|
||||
self.runCmd('type format clear', check=False)
|
||||
self.runCmd('type summary clear', check=False)
|
||||
self.runCmd('type filter clear', check=False)
|
||||
self.runCmd('type synth clear', check=False)
|
||||
self.runCmd("settings set target.max-children-count 256", check=False)
|
||||
|
||||
# Execute the cleanup function during test case tear down.
|
||||
self.addTearDownHook(cleanup)
|
||||
|
||||
self.expect('frame variable ivI', substrs = ['item = 3'])
|
||||
self.expect('expr ivI', substrs = ['item = 3'])
|
||||
|
||||
self.expect('frame variable iimI', substrs = ['first = 0','second = 12'])
|
||||
self.expect('expr iimI', substrs = ['first = 0','second = 12'])
|
||||
|
||||
self.expect('frame variable simI', substrs = ['first = "world"','second = 42'])
|
||||
self.expect('expr simI', substrs = ['first = "world"','second = 42'])
|
||||
|
||||
self.expect('frame variable svI', substrs = ['item = "hello"'])
|
||||
self.expect('expr svI', substrs = ['item = "hello"'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
import atexit
|
||||
lldb.SBDebugger.Initialize()
|
||||
atexit.register(lambda: lldb.SBDebugger.Terminate())
|
||||
unittest2.main()
|
|
@ -0,0 +1,38 @@
|
|||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
typedef std::map<int, int> intint_map;
|
||||
typedef std::map<std::string, int> strint_map;
|
||||
|
||||
typedef std::vector<int> int_vector;
|
||||
typedef std::vector<std::string> string_vector;
|
||||
|
||||
typedef intint_map::iterator iimter;
|
||||
typedef strint_map::iterator simter;
|
||||
|
||||
typedef int_vector::iterator ivter;
|
||||
typedef string_vector::iterator svter;
|
||||
|
||||
int main()
|
||||
{
|
||||
intint_map iim;
|
||||
iim[0] = 12;
|
||||
|
||||
strint_map sim;
|
||||
sim["world"] = 42;
|
||||
|
||||
int_vector iv;
|
||||
iv.push_back(3);
|
||||
|
||||
string_vector sv;
|
||||
sv.push_back("hello");
|
||||
|
||||
iimter iimI = iim.begin();
|
||||
simter simI = sim.begin();
|
||||
|
||||
ivter ivI = iv.begin();
|
||||
svter svI = sv.begin();
|
||||
|
||||
return 0; // Set break point at this line.
|
||||
}
|
Loading…
Reference in New Issue