diff --git a/lldb/include/lldb/Core/CXXFormatterFunctions.h b/lldb/include/lldb/Core/CXXFormatterFunctions.h index 1397e5e7af06de07dfa23d5db58d2fca5923ddce..7bd6ab58314ba91cdc6be5630625bd5733997954 100644 --- a/lldb/include/lldb/Core/CXXFormatterFunctions.h +++ b/lldb/include/lldb/Core/CXXFormatterFunctions.h @@ -169,6 +169,129 @@ namespace lldb_private { SyntheticChildrenFrontEnd* NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + class NSDictionaryISyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + private: + struct DataDescriptor_32 + { + uint32_t _used : 26; + uint32_t _szidx : 6; + }; + struct DataDescriptor_64 + { + uint64_t _used : 58; + uint32_t _szidx : 6; + }; + + struct DictionaryItemDescriptor + { + lldb::addr_t key_ptr; + lldb::addr_t val_ptr; + lldb::ValueObjectSP valobj_sp; + }; + + public: + NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual uint32_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (uint32_t idx); + + virtual bool + Update(); + + virtual uint32_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSDictionaryISyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + uint8_t m_ptr_size; + DataDescriptor_32 *m_data_32; + DataDescriptor_64 *m_data_64; + lldb::addr_t m_data_ptr; + std::vector m_children; + }; + + class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + private: + struct DataDescriptor_32 + { + uint32_t _used : 26; + uint32_t _kvo : 1; + uint32_t _size; + uint32_t _mutations; + uint32_t _objs_addr; + uint32_t _keys_addr; + }; + struct DataDescriptor_64 + { + uint64_t _used : 58; + uint32_t _kvo : 1; + uint64_t _size; + uint64_t _mutations; + uint64_t _objs_addr; + uint64_t _keys_addr; + }; + struct DictionaryItemDescriptor + { + lldb::addr_t key_ptr; + lldb::addr_t val_ptr; + lldb::ValueObjectSP valobj_sp; + }; + public: + NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual uint32_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (uint32_t idx); + + virtual bool + Update(); + + virtual uint32_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSDictionaryMSyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + uint8_t m_ptr_size; + uint64_t m_items; + DataDescriptor_32 *m_data_32; + DataDescriptor_64 *m_data_64; + std::vector m_children; + }; + + class NSDictionaryCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual uint32_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (uint32_t idx); + + virtual bool + Update(); + + virtual uint32_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSDictionaryCodeRunningSyntheticFrontEnd (); + }; + + SyntheticChildrenFrontEnd* NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + } } diff --git a/lldb/source/Core/CXXFormatterFunctions.cpp b/lldb/source/Core/CXXFormatterFunctions.cpp index b68ecfd1e615a61d866c28a791f885f28fb2329c..c98c8cba67815009a593b37ceed8cb544dfc76e7 100644 --- a/lldb/source/Core/CXXFormatterFunctions.cpp +++ b/lldb/source/Core/CXXFormatterFunctions.cpp @@ -1029,6 +1029,362 @@ lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetIndexOfChildWi lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::~NSArrayCodeRunningSyntheticFrontEnd () {} +SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ + + lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); + if (!process_sp) + return NULL; + ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); + if (!runtime) + return NULL; + + if (!valobj_sp->IsPointerType()) + { + Error error; + valobj_sp = valobj_sp->AddressOf(error); + if (error.Fail() || !valobj_sp) + return NULL; + } + + ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get())); + + if (!descriptor.get() || !descriptor->IsValid()) + return NULL; + + const char* class_name = descriptor->GetClassName().GetCString(); + if (!strcmp(class_name,"__NSDictionaryI")) + { + return (new NSDictionaryISyntheticFrontEnd(valobj_sp)); + } + else if (!strcmp(class_name,"__NSDictionaryM")) + { + return (new NSDictionaryMSyntheticFrontEnd(valobj_sp)); + } + else + { + return (new NSDictionaryCodeRunningSyntheticFrontEnd(valobj_sp)); + } +} + +lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()) +{} + +uint32_t +lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::CalculateNumChildren () +{ + uint64_t count = 0; + if (ExtractValueFromObjCExpression(m_backend, "int", "count", count)) + return count; + return 0; +} + +lldb::ValueObjectSP +lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIndex (uint32_t idx) +{ + StreamString idx_name; + idx_name.Printf("[%d]",idx); + StreamString valobj_expr_path; + m_backend.GetExpressionPath(valobj_expr_path, false); + StreamString key_fetcher_expr; + key_fetcher_expr.Printf("(id)[(NSArray*)[%s allKeys] objectAtIndex:%d]",valobj_expr_path.GetData(),idx); + StreamString value_fetcher_expr; + value_fetcher_expr.Printf("(id)[%s objectForKey:%s]",valobj_expr_path.GetData(),key_fetcher_expr.GetData()); + StreamString object_fetcher_expr; + object_fetcher_expr.Printf("struct { id key; id value; } _lldb_valgen_item; _lldb_valgen_item.key = %s; _lldb_valgen_item.value = %s; _lldb_valgen_item;",key_fetcher_expr.GetData(),value_fetcher_expr.GetData()); + lldb::ValueObjectSP child_sp; + m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(), m_backend.GetFrameSP().get(), child_sp, + Target::EvaluateExpressionOptions().SetKeepInMemory(true)); + if (child_sp) + child_sp->SetName(ConstString(idx_name.GetData())); + return child_sp; +} + +bool +lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::Update() +{ + return false; +} + +uint32_t +lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ + return 0; +} + +lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::~NSDictionaryCodeRunningSyntheticFrontEnd () +{} + +lldb_private::formatters::NSDictionaryISyntheticFrontEnd::NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : + SyntheticChildrenFrontEnd(*valobj_sp.get()), + m_exe_ctx_ref(), + m_ptr_size(8), + m_data_32(NULL), + m_data_64(NULL) +{ + if (!valobj_sp) + return; + if (valobj_sp->IsDynamic()) + valobj_sp = valobj_sp->GetStaticValue(); + if (!valobj_sp) + return; + m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); + Error error; + if (valobj_sp->IsPointerType()) + { + valobj_sp = valobj_sp->Dereference(error); + if (error.Fail() || !valobj_sp) + return; + } + error.Clear(); + lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); + if (!process_sp) + return; + m_ptr_size = process_sp->GetAddressByteSize(); + uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size; + if (m_ptr_size == 4) + { + m_data_32 = new DataDescriptor_32(); + process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); + } + else + { + m_data_64 = new DataDescriptor_64(); + process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); + } + if (error.Fail()) + return; + m_data_ptr = data_location + m_ptr_size; +} + +lldb_private::formatters::NSDictionaryISyntheticFrontEnd::~NSDictionaryISyntheticFrontEnd () +{ + delete m_data_32; + m_data_32 = NULL; + delete m_data_64; + m_data_64 = NULL; +} + +uint32_t +lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ + const char* item_name = name.GetCString(); + uint32_t idx = ExtractIndexFromString(item_name); + if (idx < UINT32_MAX && idx >= CalculateNumChildren()) + return UINT32_MAX; + return idx; +} + +uint32_t +lldb_private::formatters::NSDictionaryISyntheticFrontEnd::CalculateNumChildren () +{ + if (!m_data_32 && !m_data_64) + return 0; + return (m_data_32 ? m_data_32->_used : m_data_64->_used); +} + +bool +lldb_private::formatters::NSDictionaryISyntheticFrontEnd::Update() +{ + m_children.clear(); + return false; +} + +lldb::ValueObjectSP +lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex (uint32_t idx) +{ + uint32_t num_children = CalculateNumChildren(); + + if (idx >= num_children) + return lldb::ValueObjectSP(); + + if (m_children.empty()) + { + // do the scan phase + lldb::addr_t key_at_idx = 0, val_at_idx = 0; + + uint32_t tries = 0; + uint32_t test_idx = 0; + + while(tries < num_children) + { + key_at_idx = m_data_ptr + (2*test_idx * m_ptr_size); + val_at_idx = key_at_idx + m_ptr_size; + ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); + if (!process_sp) + return lldb::ValueObjectSP(); + Error error; + key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error); + if (error.Fail()) + return lldb::ValueObjectSP(); + val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error); + if (error.Fail()) + return lldb::ValueObjectSP(); + + test_idx++; + + if (!key_at_idx || !val_at_idx) + continue; + tries++; + + DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()}; + + m_children.push_back(descriptor); + } + } + + if (idx >= m_children.size()) // should never happen + return lldb::ValueObjectSP(); + + DictionaryItemDescriptor &dict_item = m_children[idx]; + if (!dict_item.valobj_sp) + { + // make the new ValueObject + StreamString expr; + expr.Printf("struct { id key; id value; } _lldb_valgen_item; _lldb_valgen_item.key = (id)%llu ; _lldb_valgen_item.value = (id)%llu; _lldb_valgen_item;",dict_item.key_ptr,dict_item.val_ptr); + StreamString idx_name; + idx_name.Printf("[%d]",idx); + dict_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref); + } + return dict_item.valobj_sp; +} + +lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : + SyntheticChildrenFrontEnd(*valobj_sp.get()), + m_exe_ctx_ref(), + m_ptr_size(8), + m_data_32(NULL), + m_data_64(NULL) +{ + if (!valobj_sp) + return; + if (valobj_sp->IsDynamic()) + valobj_sp = valobj_sp->GetStaticValue(); + if (!valobj_sp) + return; + m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); + Error error; + if (valobj_sp->IsPointerType()) + { + valobj_sp = valobj_sp->Dereference(error); + if (error.Fail() || !valobj_sp) + return; + } + error.Clear(); + lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); + if (!process_sp) + return; + m_ptr_size = process_sp->GetAddressByteSize(); + uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size; + if (m_ptr_size == 4) + { + m_data_32 = new DataDescriptor_32(); + process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); + } + else + { + m_data_64 = new DataDescriptor_64(); + process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); + } + if (error.Fail()) + return; +} + +lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd () +{ + delete m_data_32; + m_data_32 = NULL; + delete m_data_64; + m_data_64 = NULL; +} + +uint32_t +lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ + const char* item_name = name.GetCString(); + uint32_t idx = ExtractIndexFromString(item_name); + if (idx < UINT32_MAX && idx >= CalculateNumChildren()) + return UINT32_MAX; + return idx; +} + +uint32_t +lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::CalculateNumChildren () +{ + if (!m_data_32 && !m_data_64) + return 0; + return (m_data_32 ? m_data_32->_used : m_data_64->_used); +} + +bool +lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() +{ + m_children.clear(); + return false; +} + +lldb::ValueObjectSP +lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex (uint32_t idx) +{ + lldb::addr_t m_keys_ptr = (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr); + lldb::addr_t m_values_ptr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr); + + uint32_t num_children = CalculateNumChildren(); + + if (idx >= num_children) + return lldb::ValueObjectSP(); + + if (m_children.empty()) + { + // do the scan phase + lldb::addr_t key_at_idx = 0, val_at_idx = 0; + + uint32_t tries = 0; + uint32_t test_idx = 0; + + while(tries < num_children) + { + key_at_idx = m_keys_ptr + (test_idx * m_ptr_size); + val_at_idx = m_values_ptr + (test_idx * m_ptr_size);; + ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); + if (!process_sp) + return lldb::ValueObjectSP(); + Error error; + key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error); + if (error.Fail()) + return lldb::ValueObjectSP(); + val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error); + if (error.Fail()) + return lldb::ValueObjectSP(); + + test_idx++; + + if (!key_at_idx || !val_at_idx) + continue; + tries++; + + DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()}; + + m_children.push_back(descriptor); + } + } + + if (idx >= m_children.size()) // should never happen + return lldb::ValueObjectSP(); + + DictionaryItemDescriptor &dict_item = m_children[idx]; + if (!dict_item.valobj_sp) + { + // make the new ValueObject + StreamString expr; + expr.Printf("struct { id key; id value; } _lldb_valgen_item; _lldb_valgen_item.key = (id)%llu ; _lldb_valgen_item.value = (id)%llu; _lldb_valgen_item;",dict_item.key_ptr,dict_item.val_ptr); + StreamString idx_name; + idx_name.Printf("[%d]",idx); + dict_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref); + } + return dict_item.valobj_sp; +} template bool lldb_private::formatters::NSDictionarySummaryProvider (ValueObject&, Stream&) ; diff --git a/lldb/source/Core/FormatManager.cpp b/lldb/source/Core/FormatManager.cpp index f57566e81ec2f06372c156a79aab5e5b4da54542..99c7e1e982498ae0825524f7df7c13482e4ed0ed 100644 --- a/lldb/source/Core/FormatManager.cpp +++ b/lldb/source/Core/FormatManager.cpp @@ -1041,7 +1041,6 @@ FormatManager::LoadObjCFormatters() ConstString("HIRect"), objc_flags); -#ifndef LLDB_DISABLE_PYTHON TypeCategoryImpl::SharedPointer appkit_category_sp = GetCategory(m_appkit_category_name); TypeSummaryImpl::Flags appkit_flags; @@ -1064,6 +1063,16 @@ FormatManager::LoadObjCFormatters() AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFArrayRef"), appkit_flags); AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFMutableArrayRef"), appkit_flags); + AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("NSDictionary"), appkit_flags); + AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("NSMutableDictionary"), appkit_flags); + AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("__NSCFDictionary"), appkit_flags); + AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("__NSDictionaryI"), appkit_flags); + AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("__NSDictionaryM"), appkit_flags); + AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("CFDictionaryRef"), appkit_flags); + AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("CFMutableDictionaryRef"), appkit_flags); + + // AddSummary(appkit_category_sp, "${var.key%@} -> ${var.value%@}", ConstString("$_lldb_typegen_nspair"), appkit_flags); + appkit_flags.SetDontShowChildren(true); AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSArrayM"), TypeSyntheticImpl::Flags()); @@ -1072,6 +1081,14 @@ FormatManager::LoadObjCFormatters() AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("NSMutableArray"), TypeSyntheticImpl::Flags()); AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSCFArray"), TypeSyntheticImpl::Flags()); + AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSDictionaryM"), TypeSyntheticImpl::Flags()); + AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSDictionaryI"), TypeSyntheticImpl::Flags()); + AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("NSDictionary"), TypeSyntheticImpl::Flags()); + AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("NSMutableDictionary"), TypeSyntheticImpl::Flags()); + AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFDictionaryRef"), TypeSyntheticImpl::Flags()); + AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFMutableDictionaryRef"), TypeSyntheticImpl::Flags()); + +#ifndef LLDB_DISABLE_PYTHON AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFBag.CFBag_SummaryProvider", ConstString("CFBagRef"), appkit_flags); AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFBag.CFBag_SummaryProvider", ConstString("__CFBag"), appkit_flags); AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFBag.CFBag_SummaryProvider", ConstString("const struct __CFBag"), appkit_flags); @@ -1080,13 +1097,6 @@ FormatManager::LoadObjCFormatters() AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFBinaryHeap.CFBinaryHeap_SummaryProvider", ConstString("CFBinaryHeapRef"), appkit_flags); AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFBinaryHeap.CFBinaryHeap_SummaryProvider", ConstString("__CFBinaryHeap"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("NSDictionary"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("__NSCFDictionary"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("__NSDictionaryI"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("__NSDictionaryM"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("CFDictionaryRef"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("CFMutableDictionaryRef"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSString"), appkit_flags); AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFStringRef"), appkit_flags); AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFMutableStringRef"), appkit_flags); diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index a6545b19d600062c1e897a31766bc387118e125e..ab50e346e88f13fc101ae6ec25e42e4f60894ead 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -1620,6 +1620,8 @@ Target::EvaluateExpression const EvaluateExpressionOptions& options ) { + result_valobj_sp.reset(); + ExecutionResults execution_results = eExecutionSetupError; if (expr_cstr == NULL || expr_cstr[0] == '\0') diff --git a/lldb/test/functionalities/data-formatter/rdar-11988289/Makefile b/lldb/test/functionalities/data-formatter/rdar-11988289/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..9f7fb1ca623175c4285be4f49fc0eb019645ad5a --- /dev/null +++ b/lldb/test/functionalities/data-formatter/rdar-11988289/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m + +CFLAGS_EXTRAS += -w + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation diff --git a/lldb/test/functionalities/data-formatter/rdar-11988289/TestRdar 11988289.py b/lldb/test/functionalities/data-formatter/rdar-11988289/TestRdar 11988289.py new file mode 100644 index 0000000000000000000000000000000000000000..74b62088c597e4f20c9692de9e3be78cc6d5e5f8 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/rdar-11988289/TestRdar 11988289.py @@ -0,0 +1,84 @@ +""" +Test lldb data formatter subsystem. +""" + +import os, time +import unittest2 +import lldb +from lldbtest import * +import datetime + +class DataFormatterRdar11988289TestCase(TestBase): + + mydir = os.path.join("functionalities", "data-formatter", "rdar-11988289") + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + @dsym_test + def test_rdar11988289_with_dsym_and_run_command(self): + """Test that NSDictionary reports its synthetic children properly.""" + self.buildDsym() + self.rdar11988289_tester() + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + @dwarf_test + def test_rdar11988289_with_dwarf_and_run_command(self): + """Test that NSDictionary reports its synthetic children properly.""" + self.buildDwarf() + self.rdar11988289_tester() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.m', '// Set break point at this line.') + + def rdar11988289_tester(self): + """Test that NSDictionary reports its synthetic children properly.""" + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + self.expect("breakpoint set -f main.m -l %d" % self.line, + BREAKPOINT_CREATED, + startstr = "Breakpoint created: 1: file ='main.m', line = %d, locations = 1" % + self.line) + + 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 synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Now check that we are displaying Cocoa classes correctly + self.expect('frame variable dictionary', + substrs = ['3 key/value pairs']) + self.expect('frame variable mutable', + substrs = ['4 key/value pairs']) + self.expect('frame variable dictionary --ptr-depth 1', + substrs = ['3 key/value pairs','[0] = {','key = 0x','value = 0x','[1] = {','[2] = {']) + self.expect('frame variable mutable --ptr-depth 1', + substrs = ['4 key/value pairs','[0] = {','key = 0x','value = 0x','[1] = {','[2] = {','[3] = {']) + self.expect('frame variable dictionary --ptr-depth 1 -d no-run-target', + substrs = ['3 key/value pairs','@"bar"','@"2 objects"','@"baz"','2 key/value pairs']) + self.expect('frame variable mutable --ptr-depth 1 -d no-run-target', + substrs = ['4 key/value pairs','(int)23','@"123"','@"http://www.apple.com"','@"puartist"','3 key/value pairs']) + self.expect('frame variable mutable --ptr-depth 2 -d no-run-target', + substrs = ['4 key/value pairs','(int)23','@"123"','@"http://www.apple.com"','@"puartist"','3 key/value pairs {','@"bar"','@"2 objects"']) + self.expect('frame variable mutable --ptr-depth 3 -d no-run-target', + substrs = ['4 key/value pairs','(int)23','@"123"','@"http://www.apple.com"','@"puartist"','3 key/value pairs {','@"bar"','@"2 objects"','(int)1','@"two"']) + + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/functionalities/data-formatter/rdar-11988289/main.m b/lldb/test/functionalities/data-formatter/rdar-11988289/main.m new file mode 100644 index 0000000000000000000000000000000000000000..c1ab2e4018ae3d1b8f1b4af614e9a7eaa51ae943 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/rdar-11988289/main.m @@ -0,0 +1,30 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#import + +int main (int argc, const char * argv[]) +{ + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + + NSArray* keys = @[@"foo",@"bar",@"baz"]; + NSArray* values = @[@"hello",@[@"X",@"Y"],@{@1 : @"one",@2 : @"two"}]; + NSDictionary* dictionary = [NSDictionary dictionaryWithObjects:values forKeys:keys]; + NSMutableDictionary* mutable = [NSMutableDictionary dictionaryWithCapacity:5]; + [mutable setObject:@"123" forKey:@23]; + [mutable setObject:[NSURL URLWithString:@"http://www.apple.com"] forKey:@"foobar"]; + [mutable setObject:@[@"a",@12] forKey:@57]; + [mutable setObject:dictionary forKey:@"puartist"]; + + [pool drain];// Set break point at this line. + return 0; +} +