Move Objective-C data formatters to the Objective-C language plugin where they belong

llvm-svn: 247627
diff --git a/lldb/source/Plugins/Language/ObjC/CF.cpp b/lldb/source/Plugins/Language/ObjC/CF.cpp
new file mode 100644
index 0000000..fb1b871
--- /dev/null
+++ b/lldb/source/Plugins/Language/ObjC/CF.cpp
@@ -0,0 +1,298 @@
+//===-- CF.cpp ----------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CF.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/DataFormatters/FormattersHelpers.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;
+
+bool
+lldb_private::formatters::CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    time_t epoch = GetOSXEpoch();
+    epoch = epoch + (time_t)valobj.GetValueAsUnsigned(0);
+    tm *tm_date = localtime(&epoch);
+    if (!tm_date)
+        return false;
+    std::string buffer(1024,0);
+    if (strftime (&buffer[0], 1023, "%Z", tm_date) == 0)
+        return false;
+    stream.Printf("%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year+1900, tm_date->tm_mon+1, tm_date->tm_mday, tm_date->tm_hour, tm_date->tm_min, tm_date->tm_sec, buffer.c_str());
+    return true;
+}
+
+bool
+lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    uint32_t count = 0;
+    
+    bool is_type_ok = false; // check to see if this is a CFBag we know about
+    if (descriptor->IsCFType())
+    {
+        ConstString type_name(valobj.GetTypeName());
+        if (type_name == ConstString("__CFBag") || type_name == ConstString("const struct __CFBag"))
+        {
+            if (valobj.IsPointerType())
+                is_type_ok = true;
+        }
+    }
+    
+    if (is_type_ok == false)
+    {
+        StackFrameSP frame_sp(valobj.GetFrameSP());
+        if (!frame_sp)
+            return false;
+        ValueObjectSP count_sp;
+        StreamString expr;
+        expr.Printf("(int)CFBagGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue());
+        if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExpressionCompleted)
+            return false;
+        if (!count_sp)
+            return false;
+        count = count_sp->GetValueAsUnsigned(0);
+    }
+    else
+    {
+        uint32_t offset = 2*ptr_size+4 + valobj_addr;
+        Error error;
+        count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error);
+        if (error.Fail())
+            return false;
+    }
+    stream.Printf("@\"%u value%s\"",
+                  count,(count == 1 ? "" : "s"));
+    return true;
+}
+
+bool
+lldb_private::formatters::CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    uint32_t count = 0;
+    
+    bool is_type_ok = false; // check to see if this is a CFBag we know about
+    if (descriptor->IsCFType())
+    {
+        ConstString type_name(valobj.GetTypeName());
+        if (type_name == ConstString("__CFMutableBitVector") || type_name == ConstString("__CFBitVector") || type_name == ConstString("CFMutableBitVectorRef") || type_name == ConstString("CFBitVectorRef"))
+        {
+            if (valobj.IsPointerType())
+                is_type_ok = true;
+        }
+    }
+    
+    if (is_type_ok == false)
+        return false;
+    
+    Error error;
+    count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, ptr_size, 0, error);
+    if (error.Fail())
+        return false;
+    uint64_t num_bytes = count / 8 + ((count & 7) ? 1 : 0);
+    addr_t data_ptr = process_sp->ReadPointerFromMemory(valobj_addr+2*ptr_size+2*ptr_size, error);
+    if (error.Fail())
+        return false;
+    // make sure we do not try to read huge amounts of data
+    if (num_bytes > 1024)
+        num_bytes = 1024;
+    DataBufferSP buffer_sp(new DataBufferHeap(num_bytes,0));
+    num_bytes = process_sp->ReadMemory(data_ptr, buffer_sp->GetBytes(), num_bytes, error);
+    if (error.Fail() || num_bytes == 0)
+        return false;
+    uint8_t *bytes = buffer_sp->GetBytes();
+    for (uint64_t byte_idx = 0; byte_idx < num_bytes-1; byte_idx++)
+    {
+        uint8_t byte = bytes[byte_idx];
+        bool bit0 = (byte & 1) == 1;
+        bool bit1 = (byte & 2) == 2;
+        bool bit2 = (byte & 4) == 4;
+        bool bit3 = (byte & 8) == 8;
+        bool bit4 = (byte & 16) == 16;
+        bool bit5 = (byte & 32) == 32;
+        bool bit6 = (byte & 64) == 64;
+        bool bit7 = (byte & 128) == 128;
+        stream.Printf("%c%c%c%c %c%c%c%c ",
+                      (bit7 ? '1' : '0'),
+                      (bit6 ? '1' : '0'),
+                      (bit5 ? '1' : '0'),
+                      (bit4 ? '1' : '0'),
+                      (bit3 ? '1' : '0'),
+                      (bit2 ? '1' : '0'),
+                      (bit1 ? '1' : '0'),
+                      (bit0 ? '1' : '0'));
+        count -= 8;
+    }
+    {
+        // print the last byte ensuring we do not print spurious bits
+        uint8_t byte = bytes[num_bytes-1];
+        bool bit0 = (byte & 1) == 1;
+        bool bit1 = (byte & 2) == 2;
+        bool bit2 = (byte & 4) == 4;
+        bool bit3 = (byte & 8) == 8;
+        bool bit4 = (byte & 16) == 16;
+        bool bit5 = (byte & 32) == 32;
+        bool bit6 = (byte & 64) == 64;
+        bool bit7 = (byte & 128) == 128;
+        if (count)
+        {
+            stream.Printf("%c",bit7 ? '1' : '0');
+            count -= 1;
+        }
+        if (count)
+        {
+            stream.Printf("%c",bit6 ? '1' : '0');
+            count -= 1;
+        }
+        if (count)
+        {
+            stream.Printf("%c",bit5 ? '1' : '0');
+            count -= 1;
+        }
+        if (count)
+        {
+            stream.Printf("%c",bit4 ? '1' : '0');
+            count -= 1;
+        }
+        if (count)
+        {
+            stream.Printf("%c",bit3 ? '1' : '0');
+            count -= 1;
+        }
+        if (count)
+        {
+            stream.Printf("%c",bit2 ? '1' : '0');
+            count -= 1;
+        }
+        if (count)
+        {
+            stream.Printf("%c",bit1 ? '1' : '0');
+            count -= 1;
+        }
+        if (count)
+            stream.Printf("%c",bit0 ? '1' : '0');
+    }
+    return true;
+}
+
+bool
+lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    uint32_t count = 0;
+    
+    bool is_type_ok = false; // check to see if this is a CFBinaryHeap we know about
+    if (descriptor->IsCFType())
+    {
+        ConstString type_name(valobj.GetTypeName());
+        if (type_name == ConstString("__CFBinaryHeap") || type_name == ConstString("const struct __CFBinaryHeap"))
+        {
+            if (valobj.IsPointerType())
+                is_type_ok = true;
+        }
+    }
+    
+    if (is_type_ok == false)
+    {
+        StackFrameSP frame_sp(valobj.GetFrameSP());
+        if (!frame_sp)
+            return false;
+        ValueObjectSP count_sp;
+        StreamString expr;
+        expr.Printf("(int)CFBinaryHeapGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue());
+        if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExpressionCompleted)
+            return false;
+        if (!count_sp)
+            return false;
+        count = count_sp->GetValueAsUnsigned(0);
+    }
+    else
+    {
+        uint32_t offset = 2*ptr_size;
+        Error error;
+        count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error);
+        if (error.Fail())
+            return false;
+    }
+    stream.Printf("@\"%u item%s\"",
+                  count,(count == 1 ? "" : "s"));
+    return true;
+}
diff --git a/lldb/source/Plugins/Language/ObjC/CF.h b/lldb/source/Plugins/Language/ObjC/CF.h
new file mode 100644
index 0000000..4044f09
--- /dev/null
+++ b/lldb/source/Plugins/Language/ObjC/CF.h
@@ -0,0 +1,34 @@
+//===-- CF.h ---------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CF_h_
+#define liblldb_CF_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+
+namespace lldb_private {
+    namespace formatters
+    {
+        bool
+        CFBagSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        bool
+        CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        bool
+        CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        bool
+        CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+    } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_CF_h_
diff --git a/lldb/source/Plugins/Language/ObjC/CMakeLists.txt b/lldb/source/Plugins/Language/ObjC/CMakeLists.txt
index 3cd6f72..7e07bc5 100644
--- a/lldb/source/Plugins/Language/ObjC/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/ObjC/CMakeLists.txt
@@ -1,3 +1,10 @@
 add_lldb_library(lldbPluginObjCLanguage
   ObjCLanguage.cpp
+  CF.cpp
+  Cocoa.cpp
+  CoreMedia.cpp
+  NSArray.cpp
+  NSDictionary.cpp
+  NSIndexPath.cpp
+  NSSet.cpp
 )
diff --git a/lldb/source/Plugins/Language/ObjC/Coca.cpp b/lldb/source/Plugins/Language/ObjC/Coca.cpp
new file mode 100644
index 0000000..6d9ab43
--- /dev/null
+++ b/lldb/source/Plugins/Language/ObjC/Coca.cpp
@@ -0,0 +1,1150 @@
+//===-- Cocoa.cpp -------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Cocoa.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/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/ProcessStructReader.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+bool
+lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    const char* class_name = descriptor->GetClassName().GetCString();
+    
+    if (!class_name || !*class_name)
+        return false;
+    
+    if (!strcmp(class_name,"NSBundle"))
+    {
+        uint64_t offset = 5 * ptr_size;
+        ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID), true));
+
+        StreamString summary_stream;
+        bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options);
+        if (was_nsstring_ok && summary_stream.GetSize() > 0)
+        {
+            stream.Printf("%s",summary_stream.GetData());
+            return true;
+        }
+    }
+    // this is either an unknown subclass or an NSBundle that comes from [NSBundle mainBundle]
+    // which is encoded differently and needs to be handled by running code
+    return ExtractSummaryFromObjCExpression(valobj, "NSString*", "bundlePath", stream);
+}
+
+bool
+lldb_private::formatters::NSTimeZoneSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    const char* class_name = descriptor->GetClassName().GetCString();
+    
+    if (!class_name || !*class_name)
+        return false;
+    
+    if (!strcmp(class_name,"__NSTimeZone"))
+    {
+        uint64_t offset = ptr_size;
+        ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetCompilerType(), true));
+        StreamString summary_stream;
+        bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options);
+        if (was_nsstring_ok && summary_stream.GetSize() > 0)
+        {
+            stream.Printf("%s",summary_stream.GetData());
+            return true;
+        }
+    }
+    return ExtractSummaryFromObjCExpression(valobj, "NSString*", "name", stream);
+}
+
+bool
+lldb_private::formatters::NSNotificationSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    const char* class_name = descriptor->GetClassName().GetCString();
+    
+    if (!class_name || !*class_name)
+        return false;
+    
+    if (!strcmp(class_name,"NSConcreteNotification"))
+    {
+        uint64_t offset = ptr_size;
+        ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetCompilerType(), true));
+        StreamString summary_stream;
+        bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options);
+        if (was_nsstring_ok && summary_stream.GetSize() > 0)
+        {
+            stream.Printf("%s",summary_stream.GetData());
+            return true;
+        }
+    }
+    // this is either an unknown subclass or an NSBundle that comes from [NSBundle mainBundle]
+    // which is encoded differently and needs to be handled by running code
+    return ExtractSummaryFromObjCExpression(valobj, "NSString*", "name", stream);
+}
+
+bool
+lldb_private::formatters::NSMachPortSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    const char* class_name = descriptor->GetClassName().GetCString();
+    
+    if (!class_name || !*class_name)
+        return false;
+    
+    uint64_t port_number = 0;
+    
+    do
+    {
+        if (!strcmp(class_name,"NSMachPort"))
+        {
+            uint64_t offset = (ptr_size == 4 ? 12 : 20);
+            Error error;
+            port_number = process_sp->ReadUnsignedIntegerFromMemory(offset+valobj_addr, 4, 0, error);
+            if (error.Success())
+                break;
+        }
+        if (!ExtractValueFromObjCExpression(valobj, "int", "machPort", port_number))
+            return false;
+    } while (false);
+    
+    stream.Printf("mach port: %u",(uint32_t)(port_number & 0x00000000FFFFFFFF));
+    return true;
+}
+
+bool
+lldb_private::formatters::NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    const char* class_name = descriptor->GetClassName().GetCString();
+    
+    if (!class_name || !*class_name)
+        return false;
+    
+    uint64_t count = 0;
+    
+    do {
+        if (!strcmp(class_name,"NSIndexSet") || !strcmp(class_name,"NSMutableIndexSet"))
+        {
+            Error error;
+            uint32_t mode = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+ptr_size, 4, 0, error);
+            if (error.Fail())
+                return false;
+            // this means the set is empty - count = 0
+            if ((mode & 1) == 1)
+            {
+                count = 0;
+                break;
+            }
+            if ((mode & 2) == 2)
+                mode = 1; // this means the set only has one range
+            else
+                mode = 2; // this means the set has multiple ranges
+            if (mode == 1)
+            {
+                count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+3*ptr_size, ptr_size, 0, error);
+                if (error.Fail())
+                    return false;
+            }
+            else
+            {
+                // read a pointer to the data at 2*ptr_size
+                count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, ptr_size, 0, error);
+                if (error.Fail())
+                    return false;
+                // read the data at 2*ptr_size from the first location
+                count = process_sp->ReadUnsignedIntegerFromMemory(count+2*ptr_size, ptr_size, 0, error);
+                if (error.Fail())
+                    return false;
+            }
+        }
+        else
+        {
+            if (!ExtractValueFromObjCExpression(valobj, "unsigned long long int", "count", count))
+                return false;
+        }
+    }  while (false);
+    stream.Printf("%" PRIu64 " index%s",
+                  count,
+                  (count == 1 ? "" : "es"));
+    return true;
+}
+
+bool
+lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    const char* class_name = descriptor->GetClassName().GetCString();
+    
+    if (!class_name || !*class_name)
+        return false;
+    
+    if (!strcmp(class_name,"NSNumber") || !strcmp(class_name,"__NSCFNumber"))
+    {
+        uint64_t value = 0;
+        uint64_t i_bits = 0;
+        if (descriptor->GetTaggedPointerInfo(&i_bits,&value))
+        {
+            switch (i_bits)
+            {
+                case 0:
+                    stream.Printf("(char)%hhd",(char)value);
+                    break;
+                case 1:
+                case 4:
+                    stream.Printf("(short)%hd",(short)value);
+                    break;
+                case 2:
+                case 8:
+                    stream.Printf("(int)%d",(int)value);
+                    break;
+                case 3:
+                case 12:
+                    stream.Printf("(long)%" PRId64,value);
+                    break;
+                default:
+                    return false;
+            }
+            return true;
+        }
+        else
+        {
+            Error error;
+            uint8_t data_type = (process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 1, 0, error) & 0x1F);
+            uint64_t data_location = valobj_addr + 2*ptr_size;
+            uint64_t value = 0;
+            if (error.Fail())
+                return false;
+            switch (data_type)
+            {
+                case 1: // 0B00001
+                    value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0, error);
+                    if (error.Fail())
+                        return false;
+                    stream.Printf("(char)%hhd",(char)value);
+                    break;
+                case 2: // 0B0010
+                    value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0, error);
+                    if (error.Fail())
+                        return false;
+                    stream.Printf("(short)%hd",(short)value);
+                    break;
+                case 3: // 0B0011
+                    value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, error);
+                    if (error.Fail())
+                        return false;
+                    stream.Printf("(int)%d",(int)value);
+                    break;
+                case 17: // 0B10001
+                    data_location += 8;
+                case 4: // 0B0100
+                    value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error);
+                    if (error.Fail())
+                        return false;
+                    stream.Printf("(long)%" PRId64,value);
+                    break;
+                case 5: // 0B0101
+                {
+                    uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, error);
+                    if (error.Fail())
+                        return false;
+                    float flt_value = *((float*)&flt_as_int);
+                    stream.Printf("(float)%f",flt_value);
+                    break;
+                }
+                case 6: // 0B0110
+                {
+                    uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error);
+                    if (error.Fail())
+                        return false;
+                    double dbl_value = *((double*)&dbl_as_lng);
+                    stream.Printf("(double)%g",dbl_value);
+                    break;
+                }
+                default:
+                    return false;
+            }
+            return true;
+        }
+    }
+    else
+    {
+        return ExtractSummaryFromObjCExpression(valobj, "NSString*", "stringValue", stream);
+    }
+}
+
+bool
+lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    const char* class_name = descriptor->GetClassName().GetCString();
+    
+    if (!class_name || !*class_name)
+        return false;
+    
+    if (strcmp(class_name, "NSURL") == 0)
+    {
+        uint64_t offset_text = ptr_size + ptr_size + 8; // ISA + pointer + 8 bytes of data (even on 32bit)
+        uint64_t offset_base = offset_text + ptr_size;
+        CompilerType type(valobj.GetCompilerType());
+        ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset_text, type, true));
+        ValueObjectSP base(valobj.GetSyntheticChildAtOffset(offset_base, type, true));
+        if (!text)
+            return false;
+        if (text->GetValueAsUnsigned(0) == 0)
+            return false;
+        StreamString summary;
+        if (!NSStringSummaryProvider(*text, summary, options))
+            return false;
+        if (base && base->GetValueAsUnsigned(0))
+        {
+            if (summary.GetSize() > 0)
+                summary.GetString().resize(summary.GetSize()-1);
+            summary.Printf(" -- ");
+            StreamString base_summary;
+            if (NSURLSummaryProvider(*base, base_summary, options) && base_summary.GetSize() > 0)
+                summary.Printf("%s",base_summary.GetSize() > 2 ? base_summary.GetData() + 2 : base_summary.GetData());
+        }
+        if (summary.GetSize())
+        {
+            stream.Printf("%s",summary.GetData());
+            return true;
+        }
+    }
+    else
+    {
+        return ExtractSummaryFromObjCExpression(valobj, "NSString*", "description", stream);
+    }
+    return false;
+}
+
+bool
+lldb_private::formatters::NSDateSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    uint64_t date_value_bits = 0;
+    double date_value = 0.0;
+    
+    const char* class_name = descriptor->GetClassName().GetCString();
+    
+    if (!class_name || !*class_name)
+        return false;
+    
+    if (strcmp(class_name,"NSDate") == 0 ||
+        strcmp(class_name,"__NSDate") == 0 ||
+        strcmp(class_name,"__NSTaggedDate") == 0)
+    {
+        uint64_t info_bits=0,value_bits = 0;
+        if (descriptor->GetTaggedPointerInfo(&info_bits,&value_bits))
+        {
+            date_value_bits = ((value_bits << 8) | (info_bits << 4));
+            date_value = *((double*)&date_value_bits);
+        }
+        else
+        {
+            Error error;
+            date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+ptr_size, 8, 0, error);
+            date_value = *((double*)&date_value_bits);
+            if (error.Fail())
+                return false;
+        }
+    }
+    else if (!strcmp(class_name,"NSCalendarDate"))
+    {
+        Error error;
+        date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, 8, 0, error);
+        date_value = *((double*)&date_value_bits);
+        if (error.Fail())
+            return false;
+    }
+    else
+    {
+        if (ExtractValueFromObjCExpression(valobj, "NSTimeInterval", "ExtractValueFromObjCExpression", date_value_bits) == false)
+            return false;
+        date_value = *((double*)&date_value_bits);
+    }
+    if (date_value == -63114076800)
+    {
+        stream.Printf("0001-12-30 00:00:00 +0000");
+        return true;
+    }
+    // this snippet of code assumes that time_t == seconds since Jan-1-1970
+    // this is generally true and POSIXly happy, but might break if a library
+    // vendor decides to get creative
+    time_t epoch = GetOSXEpoch();
+    epoch = epoch + (time_t)date_value;
+    tm *tm_date = gmtime(&epoch);
+    if (!tm_date)
+        return false;
+    std::string buffer(1024,0);
+    if (strftime (&buffer[0], 1023, "%Z", tm_date) == 0)
+        return false;
+    stream.Printf("%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year+1900, tm_date->tm_mon+1, tm_date->tm_mday, tm_date->tm_hour, tm_date->tm_min, tm_date->tm_sec, buffer.c_str());
+    return true;
+}
+
+bool
+lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    const char* class_name = descriptor->GetClassName().GetCString();
+    
+    if (!class_name || !*class_name)
+        return false;
+    
+    stream.Printf("%s",class_name);
+    return true;
+}
+
+class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
+{
+public:
+    ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
+    SyntheticChildrenFrontEnd(*valobj_sp.get())
+    {
+    }
+    
+    virtual size_t
+    CalculateNumChildren ()
+    {
+        return 0;
+    }
+    
+    virtual lldb::ValueObjectSP
+    GetChildAtIndex (size_t idx)
+    {
+        return lldb::ValueObjectSP();
+    }
+    
+    virtual bool
+    Update()
+    {
+        return false;
+    }
+    
+    virtual bool
+    MightHaveChildren ()
+    {
+        return false;
+    }
+    
+    virtual size_t
+    GetIndexOfChildWithName (const ConstString &name)
+    {
+        return UINT32_MAX;
+    }
+    
+    virtual
+    ~ObjCClassSyntheticChildrenFrontEnd ()
+    {
+    }
+};
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+    return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
+}
+
+template<bool needs_at>
+bool
+lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    bool is_64bit = (process_sp->GetAddressByteSize() == 8);
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    uint64_t value = 0;
+    
+    const char* class_name = descriptor->GetClassName().GetCString();
+    
+    if (!class_name || !*class_name)
+        return false;
+    
+    if (!strcmp(class_name,"NSConcreteData") ||
+        !strcmp(class_name,"NSConcreteMutableData") ||
+        !strcmp(class_name,"__NSCFData"))
+    {
+        uint32_t offset = (is_64bit ? 16 : 8);
+        Error error;
+        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
+        if (error.Fail())
+            return false;
+    }
+    else
+    {
+        if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
+            return false;
+    }
+    
+    stream.Printf("%s%" PRIu64 " byte%s%s",
+                  (needs_at ? "@\"" : ""),
+                  value,
+                  (value != 1 ? "s" : ""),
+                  (needs_at ? "\"" : ""));
+    
+    return true;
+}
+
+bool
+lldb_private::formatters::NSTaggedString_SummaryProvider (ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream)
+{
+    if (!descriptor)
+        return false;
+    uint64_t len_bits = 0, data_bits = 0;
+    if (!descriptor->GetTaggedPointerInfo(&len_bits,&data_bits,nullptr))
+        return false;
+    
+    static const int g_MaxNonBitmaskedLen = 7; //TAGGED_STRING_UNPACKED_MAXLEN
+    static const int g_SixbitMaxLen = 9;
+    static const int g_fiveBitMaxLen = 11;
+    
+    static const char *sixBitToCharLookup = "eilotrm.apdnsIc ufkMShjTRxgC4013" "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX";
+    
+    if (len_bits > g_fiveBitMaxLen)
+        return false;
+    
+    // this is a fairly ugly trick - pretend that the numeric value is actually a char*
+    // this works under a few assumptions:
+    // little endian architecture
+    // sizeof(uint64_t) > g_MaxNonBitmaskedLen
+    if (len_bits <= g_MaxNonBitmaskedLen)
+    {
+        stream.Printf("@\"%s\"",(const char*)&data_bits);
+        return true;
+    }
+    
+    // if the data is bitmasked, we need to actually process the bytes
+    uint8_t bitmask = 0;
+    uint8_t shift_offset = 0;
+    
+    if (len_bits <= g_SixbitMaxLen)
+    {
+        bitmask = 0x03f;
+        shift_offset = 6;
+    }
+    else
+    {
+        bitmask = 0x01f;
+        shift_offset = 5;
+    }
+    
+    std::vector<uint8_t> bytes;
+    bytes.resize(len_bits);
+    for (; len_bits > 0; data_bits >>= shift_offset, --len_bits)
+    {
+        uint8_t packed = data_bits & bitmask;
+        bytes.insert(bytes.begin(), sixBitToCharLookup[packed]);
+    }
+    
+    stream.Printf("@\"%s\"",&bytes[0]);
+    return true;
+}
+
+static CompilerType
+GetNSPathStore2Type (Target &target)
+{
+    static ConstString g_type_name("__lldb_autogen_nspathstore2");
+    
+    ClangASTContext *ast_ctx = target.GetScratchClangASTContext();
+    
+    if (!ast_ctx)
+        return CompilerType();
+    
+    CompilerType voidstar = ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
+    CompilerType uint32 = ast_ctx->GetIntTypeFromBitSize(32, false);
+    
+    return ast_ctx->GetOrCreateStructForIdentifier(g_type_name, {
+        {"isa",voidstar},
+        {"lengthAndRef",uint32},
+        {"buffer",voidstar}
+    });
+}
+
+bool
+lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    const char* class_name = descriptor->GetClassName().GetCString();
+    
+    if (!class_name || !*class_name)
+        return false;
+    
+    bool is_tagged_ptr = (0 == strcmp(class_name,"NSTaggedPointerString")) && descriptor->GetTaggedPointerInfo();
+    // for a tagged pointer, the descriptor has everything we need
+    if (is_tagged_ptr)
+        return NSTaggedString_SummaryProvider(descriptor, stream);
+    
+    // if not a tagged pointer that we know about, try the normal route
+    uint64_t info_bits_location = valobj_addr + ptr_size;
+    if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
+        info_bits_location += 3;
+    
+    Error error;
+    
+    uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
+    if (error.Fail())
+        return false;
+    
+    bool is_mutable = (info_bits & 1) == 1;
+    bool is_inline = (info_bits & 0x60) == 0;
+    bool has_explicit_length = (info_bits & (1 | 4)) != 4;
+    bool is_unicode = (info_bits & 0x10) == 0x10;
+    bool is_path_store = strcmp(class_name,"NSPathStore2") == 0;
+    bool has_null = (info_bits & 8) == 8;
+    
+    size_t explicit_length = 0;
+    if (!has_null && has_explicit_length && !is_path_store)
+    {
+        lldb::addr_t explicit_length_offset = 2*ptr_size;
+        if (is_mutable && !is_inline)
+            explicit_length_offset = explicit_length_offset + ptr_size; //  notInlineMutable.length;
+        else if (is_inline)
+            explicit_length = explicit_length + 0; // inline1.length;
+        else if (!is_inline && !is_mutable)
+            explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
+        else
+            explicit_length_offset = 0;
+        
+        if (explicit_length_offset)
+        {
+            explicit_length_offset = valobj_addr + explicit_length_offset;
+            explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
+        }
+    }
+    
+    if (strcmp(class_name,"NSString") &&
+        strcmp(class_name,"CFStringRef") &&
+        strcmp(class_name,"CFMutableStringRef") &&
+        strcmp(class_name,"__NSCFConstantString") &&
+        strcmp(class_name,"__NSCFString") &&
+        strcmp(class_name,"NSCFConstantString") &&
+        strcmp(class_name,"NSCFString") &&
+        strcmp(class_name,"NSPathStore2"))
+    {
+        // not one of us - but tell me class name
+        stream.Printf("class name = %s",class_name);
+        return true;
+    }
+    
+    if (is_mutable)
+    {
+        uint64_t location = 2 * ptr_size + valobj_addr;
+        location = process_sp->ReadPointerFromMemory(location, error);
+        if (error.Fail())
+            return false;
+        if (has_explicit_length && is_unicode)
+        {
+            StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+            options.SetLocation(location);
+            options.SetProcessSP(process_sp);
+            options.SetStream(&stream);
+            options.SetPrefixToken('@');
+            options.SetQuote('"');
+            options.SetSourceSize(explicit_length);
+            options.SetNeedsZeroTermination(false);
+            options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+            options.SetBinaryZeroIsTerminator(false);
+            return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16>(options);
+        }
+        else
+        {
+            StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+            options.SetLocation(location+1);
+            options.SetProcessSP(process_sp);
+            options.SetStream(&stream);
+            options.SetPrefixToken('@');
+            options.SetSourceSize(explicit_length);
+            options.SetNeedsZeroTermination(false);
+            options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+            options.SetBinaryZeroIsTerminator(false);
+            return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII>(options);
+        }
+    }
+    else if (is_inline && has_explicit_length && !is_unicode && !is_path_store && !is_mutable)
+    {
+        uint64_t location = 3 * ptr_size + valobj_addr;
+        
+        StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+        options.SetLocation(location);
+        options.SetProcessSP(process_sp);
+        options.SetStream(&stream);
+        options.SetPrefixToken('@');
+        options.SetQuote('"');
+        options.SetSourceSize(explicit_length);
+        options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+        return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII> (options);
+    }
+    else if (is_unicode)
+    {
+        uint64_t location = valobj_addr + 2*ptr_size;
+        if (is_inline)
+        {
+            if (!has_explicit_length)
+            {
+                stream.Printf("found new combo");
+                return true;
+            }
+            else
+                location += ptr_size;
+        }
+        else
+        {
+            location = process_sp->ReadPointerFromMemory(location, error);
+            if (error.Fail())
+                return false;
+        }
+        StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+        options.SetLocation(location);
+        options.SetProcessSP(process_sp);
+        options.SetStream(&stream);
+        options.SetPrefixToken('@');
+        options.SetQuote('"');
+        options.SetSourceSize(explicit_length);
+        options.SetNeedsZeroTermination(has_explicit_length == false);
+        options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+        options.SetBinaryZeroIsTerminator(has_explicit_length == false);
+        return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16> (options);
+    }
+    else if (is_path_store)
+    {
+        ProcessStructReader reader(valobj.GetProcessSP().get(), valobj.GetValueAsUnsigned(0), GetNSPathStore2Type(*valobj.GetTargetSP()));
+        explicit_length = reader.GetField<uint32_t>(ConstString("lengthAndRef")) >> 20;
+        lldb::addr_t location = valobj.GetValueAsUnsigned(0) + ptr_size + 4;
+        
+        StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+        options.SetLocation(location);
+        options.SetProcessSP(process_sp);
+        options.SetStream(&stream);
+        options.SetPrefixToken('@');
+        options.SetQuote('"');
+        options.SetSourceSize(explicit_length);
+        options.SetNeedsZeroTermination(has_explicit_length == false);
+        options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+        options.SetBinaryZeroIsTerminator(has_explicit_length == false);
+        return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16> (options);
+    }
+    else if (is_inline)
+    {
+        uint64_t location = valobj_addr + 2*ptr_size;
+        if (!has_explicit_length)
+        {
+            // in this kind of string, the byte before the string content is a length byte
+            // so let's try and use it to handle the embedded NUL case
+            Error error;
+            explicit_length = process_sp->ReadUnsignedIntegerFromMemory(location, 1, 0, error);
+            if (error.Fail() || explicit_length == 0)
+                has_explicit_length = false;
+            else
+                has_explicit_length = true;
+            location++;
+        }
+        StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+        options.SetLocation(location);
+        options.SetProcessSP(process_sp);
+        options.SetStream(&stream);
+        options.SetPrefixToken('@');
+        options.SetSourceSize(explicit_length);
+        options.SetNeedsZeroTermination(!has_explicit_length);
+        options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+        options.SetBinaryZeroIsTerminator(!has_explicit_length);
+        if (has_explicit_length)
+            return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options);
+        else
+            return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII>(options);
+    }
+    else
+    {
+        uint64_t location = valobj_addr + 2*ptr_size;
+        location = process_sp->ReadPointerFromMemory(location, error);
+        if (error.Fail())
+            return false;
+        if (has_explicit_length && !has_null)
+            explicit_length++; // account for the fact that there is no NULL and we need to have one added
+        StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+        options.SetLocation(location);
+        options.SetProcessSP(process_sp);
+        options.SetPrefixToken('@');
+        options.SetStream(&stream);
+        options.SetSourceSize(explicit_length);
+        options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+        return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII>(options);
+    }
+}
+
+bool
+lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    TargetSP target_sp(valobj.GetTargetSP());
+    if (!target_sp)
+        return false;
+    uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
+    uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
+    if (!pointer_value)
+        return false;
+    pointer_value += addr_size;
+    CompilerType type(valobj.GetCompilerType());
+    ExecutionContext exe_ctx(target_sp,false);
+    ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type));
+    if (!child_ptr_sp)
+        return false;
+    DataExtractor data;
+    Error error;
+    child_ptr_sp->GetData(data, error);
+    if (error.Fail())
+        return false;
+    ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
+    child_sp->GetValueAsUnsigned(0);
+    if (child_sp)
+        return NSStringSummaryProvider(*child_sp, stream, options);
+    return false;
+}
+
+bool
+lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    return NSAttributedStringSummaryProvider(valobj, stream, options);
+}
+
+bool
+lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    const uint32_t type_info = valobj.GetCompilerType().GetTypeInfo();
+    
+    ValueObjectSP real_guy_sp = valobj.GetSP();
+    
+    if (type_info & eTypeIsPointer)
+    {
+        Error err;
+        real_guy_sp = valobj.Dereference(err);
+        if (err.Fail() || !real_guy_sp)
+            return false;
+    }
+    else if (type_info & eTypeIsReference)
+    {
+        real_guy_sp =  valobj.GetChildAtIndex(0, true);
+        if (!real_guy_sp)
+            return false;
+    }
+    uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
+    if (value == 0)
+    {
+        stream.Printf("NO");
+        return true;
+    }
+    stream.Printf("YES");
+    return true;
+}
+
+template <bool is_sel_ptr>
+bool
+lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    lldb::ValueObjectSP valobj_sp;
+    
+    CompilerType charstar (valobj.GetCompilerType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
+    
+    if (!charstar)
+        return false;
+    
+    ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
+    
+    if (is_sel_ptr)
+    {
+        lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+        if (data_address == LLDB_INVALID_ADDRESS)
+            return false;
+        valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
+    }
+    else
+    {
+        DataExtractor data;
+        Error error;
+        valobj.GetData(data, error);
+        if (error.Fail())
+            return false;
+        valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
+    }
+    
+    if (!valobj_sp)
+        return false;
+    
+    stream.Printf("%s",valobj_sp->GetSummaryAsCString());
+    return true;
+}
+
+// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
+// this call gives the POSIX equivalent of the Cocoa epoch
+time_t
+lldb_private::formatters::GetOSXEpoch ()
+{
+    static time_t epoch = 0;
+    if (!epoch)
+    {
+#ifndef _WIN32
+        tzset();
+        tm tm_epoch;
+        tm_epoch.tm_sec = 0;
+        tm_epoch.tm_hour = 0;
+        tm_epoch.tm_min = 0;
+        tm_epoch.tm_mon = 0;
+        tm_epoch.tm_mday = 1;
+        tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
+        tm_epoch.tm_isdst = -1;
+        tm_epoch.tm_gmtoff = 0;
+        tm_epoch.tm_zone = NULL;
+        epoch = timegm(&tm_epoch);
+#endif
+    }
+    return epoch;
+}
+
+bool
+lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    stream.Printf("%s",valobj.GetObjectDescription());
+    return true;
+}
+
+template bool
+lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+
+template bool
+lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+
+template bool
+lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+
+template bool
+lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
diff --git a/lldb/source/Plugins/Language/ObjC/Cocoa.h b/lldb/source/Plugins/Language/ObjC/Cocoa.h
new file mode 100644
index 0000000..f29e7d1
--- /dev/null
+++ b/lldb/source/Plugins/Language/ObjC/Cocoa.h
@@ -0,0 +1,115 @@
+//===-- Cocoa.h ---------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Cocoa_h_
+#define liblldb_Cocoa_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+
+namespace lldb_private {
+    namespace formatters
+    {
+        template<bool name_entries>
+        bool
+        NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        bool
+        NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        bool
+        NSArraySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        template<bool cf_style>
+        bool
+        NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        template<bool needs_at>
+        bool
+        NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        bool
+        NSNumberSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        bool
+        NSNotificationSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        bool
+        NSTimeZoneSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        bool
+        NSMachPortSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        bool
+        NSDateSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        bool
+        NSBundleSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        bool
+        NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        bool
+        NSTaggedString_SummaryProvider (ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream);
+        
+        bool
+        NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        bool
+        NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        bool
+        NSURLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        extern template bool
+        NSDictionarySummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+        
+        extern template bool
+        NSDictionarySummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+        
+        extern template bool
+        NSDataSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+        
+        extern template bool
+        NSDataSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+        
+        SyntheticChildrenFrontEnd* NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+        
+        SyntheticChildrenFrontEnd* NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+        
+        SyntheticChildrenFrontEnd* NSSetSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+        
+        SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+        
+        bool
+        ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        SyntheticChildrenFrontEnd* ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+        
+        bool
+        ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        template <bool is_sel_ptr>
+        bool
+        ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+        
+        extern template bool
+        ObjCSELSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&);
+        
+        extern template bool
+        ObjCSELSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&);
+        
+        bool
+        RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+    } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_Cocoa_h_
diff --git a/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp b/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp
new file mode 100644
index 0000000..bc7a933
--- /dev/null
+++ b/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp
@@ -0,0 +1,89 @@
+//===-- CoreMedia.cpp --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CoreMedia.h"
+
+#include "lldb/Core/Flags.h"
+#include "lldb/Symbol/TypeSystem.h"
+#include "lldb/Target/Target.h"
+#include <inttypes.h>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+bool
+lldb_private::formatters::CMTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    CompilerType type = valobj.GetCompilerType();
+    if (!type.IsValid())
+        return false;
+
+    TypeSystem *type_system = valobj.GetExecutionContextRef().GetTargetSP()->GetTypeSystemForLanguage(lldb::eLanguageTypeC);
+    if (!type_system)
+        return false;
+    
+    // fetch children by offset to compensate for potential lack of debug info
+    auto int64_ty = type_system->GetIntTypeFromBitSize(64, true);
+    auto int32_ty = type_system->GetIntTypeFromBitSize(32, true);
+    
+    auto value_sp(valobj.GetSyntheticChildAtOffset(0, int64_ty, true));
+    auto timescale_sp(valobj.GetSyntheticChildAtOffset(8, int32_ty, true));
+    auto flags_sp(valobj.GetSyntheticChildAtOffset(12, int32_ty, true));
+    
+    if (!value_sp || !timescale_sp || !flags_sp)
+        return false;
+    
+    auto value = value_sp->GetValueAsUnsigned(0);
+    auto timescale = (int32_t)timescale_sp->GetValueAsUnsigned(0); // the timescale specifies the fraction of a second each unit in the numerator occupies
+    auto flags = Flags(flags_sp->GetValueAsUnsigned(0) & 0x00000000000000FF); // the flags I need sit in the LSB
+    
+    const unsigned int FlagPositiveInf = 4;
+    const unsigned int FlagNegativeInf = 8;
+    const unsigned int FlagIndefinite = 16;
+    
+    if (flags.AnySet(FlagIndefinite))
+    {
+        stream.Printf("indefinite");
+        return true;
+    }
+    
+    if (flags.AnySet(FlagPositiveInf))
+    {
+        stream.Printf("+oo");
+        return true;
+    }
+    
+    if (flags.AnySet(FlagNegativeInf))
+    {
+        stream.Printf("-oo");
+        return true;
+    }
+    
+    if (timescale == 0)
+        return false;
+    
+    switch (timescale)
+    {
+        case 0:
+            return false;
+        case 1:
+            stream.Printf("%" PRId64 " seconds", value);
+            return true;
+        case 2:
+            stream.Printf("%" PRId64 " half seconds", value);
+            return true;
+        case 3:
+            stream.Printf("%" PRId64 " third%sof a second", value, value == 1 ? " " : "s ");
+            return true;
+        default:
+            stream.Printf("%" PRId64 " %" PRId32 "th%sof a second", value, timescale, value == 1 ? " " : "s ");
+            return true;
+    }
+}
diff --git a/lldb/source/Plugins/Language/ObjC/CoreMedia.h b/lldb/source/Plugins/Language/ObjC/CoreMedia.h
new file mode 100644
index 0000000..2ffabaa
--- /dev/null
+++ b/lldb/source/Plugins/Language/ObjC/CoreMedia.h
@@ -0,0 +1,26 @@
+//===-- CoreMedia.h -----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CoreMedia_h_
+#define liblldb_CoreMedia_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+
+namespace lldb_private {
+    namespace formatters
+    {
+        
+        bool
+        CMTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+    } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_CF_h_
diff --git a/lldb/source/Plugins/Language/ObjC/NSArray.cpp b/lldb/source/Plugins/Language/ObjC/NSArray.cpp
new file mode 100644
index 0000000..d5466ed
--- /dev/null
+++ b/lldb/source/Plugins/Language/ObjC/NSArray.cpp
@@ -0,0 +1,711 @@
+//===-- NSArray.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Cocoa.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/DataFormatters/FormattersHelpers.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
+#include "lldb/Target/Target.h"
+
+#include "clang/AST/ASTContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace  lldb_private {
+    namespace formatters {
+        class NSArrayMSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+        {
+        public:
+            NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+            
+            virtual size_t
+            CalculateNumChildren ();
+            
+            virtual lldb::ValueObjectSP
+            GetChildAtIndex (size_t idx);
+            
+            virtual bool
+            Update() = 0;
+            
+            virtual bool
+            MightHaveChildren ();
+            
+            virtual size_t
+            GetIndexOfChildWithName (const ConstString &name);
+            
+            virtual
+            ~NSArrayMSyntheticFrontEnd () {}
+            
+        protected:
+            virtual lldb::addr_t
+            GetDataAddress () = 0;
+            
+            virtual uint64_t
+            GetUsedCount () = 0;
+            
+            virtual uint64_t
+            GetOffset () = 0;
+            
+            virtual uint64_t
+            GetSize () = 0;
+            
+            ExecutionContextRef m_exe_ctx_ref;
+            uint8_t m_ptr_size;
+            CompilerType m_id_type;
+            std::vector<lldb::ValueObjectSP> m_children;
+        };
+        
+        class NSArrayMSyntheticFrontEnd_109 : public NSArrayMSyntheticFrontEnd
+        {
+        private:
+            struct DataDescriptor_32
+            {
+                uint32_t _used;
+                uint32_t _priv1 : 2 ;
+                uint32_t _size : 30;
+                uint32_t _priv2 : 2;
+                uint32_t _offset : 30;
+                uint32_t _priv3;
+                uint32_t _data;
+            };
+            struct DataDescriptor_64
+            {
+                uint64_t _used;
+                uint64_t _priv1 : 2 ;
+                uint64_t _size : 62;
+                uint64_t _priv2 : 2;
+                uint64_t _offset : 62;
+                uint32_t _priv3;
+                uint64_t _data;
+            };
+        public:
+            NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp);
+            
+            virtual bool
+            Update();
+            
+            virtual
+            ~NSArrayMSyntheticFrontEnd_109 ();
+            
+        protected:
+            virtual lldb::addr_t
+            GetDataAddress ();
+            
+            virtual uint64_t
+            GetUsedCount ();
+            
+            virtual uint64_t
+            GetOffset ();
+            
+            virtual uint64_t
+            GetSize ();
+            
+        private:
+            DataDescriptor_32 *m_data_32;
+            DataDescriptor_64 *m_data_64;
+        };
+        
+        class NSArrayMSyntheticFrontEnd_1010 : public NSArrayMSyntheticFrontEnd
+        {
+        private:
+            struct DataDescriptor_32
+            {
+                uint32_t _used;
+                uint32_t _offset;
+                uint32_t _size : 28;
+                uint64_t _priv1 : 4;
+                uint32_t _priv2;
+                uint32_t _data;
+            };
+            struct DataDescriptor_64
+            {
+                uint64_t _used;
+                uint64_t _offset;
+                uint64_t _size : 60;
+                uint64_t _priv1 : 4;
+                uint32_t _priv2;
+                uint64_t _data;
+            };
+        public:
+            NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp);
+            
+            virtual bool
+            Update();
+            
+            virtual
+            ~NSArrayMSyntheticFrontEnd_1010 ();
+            
+        protected:
+            virtual lldb::addr_t
+            GetDataAddress ();
+            
+            virtual uint64_t
+            GetUsedCount ();
+            
+            virtual uint64_t
+            GetOffset ();
+            
+            virtual uint64_t
+            GetSize ();
+            
+        private:
+            DataDescriptor_32 *m_data_32;
+            DataDescriptor_64 *m_data_64;
+        };
+        
+        class NSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd
+        {
+        public:
+            NSArrayISyntheticFrontEnd (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
+            ~NSArrayISyntheticFrontEnd ();
+        private:
+            ExecutionContextRef m_exe_ctx_ref;
+            uint8_t m_ptr_size;
+            uint64_t m_items;
+            lldb::addr_t m_data_ptr;
+            CompilerType m_id_type;
+            std::vector<lldb::ValueObjectSP> m_children;
+        };
+        
+        class NSArrayCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+        {
+        public:
+            NSArrayCodeRunningSyntheticFrontEnd (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
+            ~NSArrayCodeRunningSyntheticFrontEnd ();
+        };
+    }
+}
+
+bool
+lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    uint64_t value = 0;
+    
+    const char* class_name = descriptor->GetClassName().GetCString();
+    
+    if (!class_name || !*class_name)
+        return false;
+    
+    if (!strcmp(class_name,"__NSArrayI"))
+    {
+        Error error;
+        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
+        if (error.Fail())
+            return false;
+    }
+    else if (!strcmp(class_name,"__NSArrayM"))
+    {
+        Error error;
+        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
+        if (error.Fail())
+            return false;
+    }
+    else if (!strcmp(class_name,"__NSCFArray"))
+    {
+        Error error;
+        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + 2 * ptr_size, ptr_size, 0, error);
+        if (error.Fail())
+            return false;
+    }
+    else
+    {
+        if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
+            return false;
+    }
+    
+    stream.Printf("@\"%" PRIu64 " object%s\"",
+                  value,
+                  value == 1 ? "" : "s");
+    return true;
+}
+
+lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp),
+    m_exe_ctx_ref(),
+    m_ptr_size(8),
+m_id_type(),
+m_children()
+{
+    if (valobj_sp)
+    {
+        clang::ASTContext *ast = valobj_sp->GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext()->getASTContext();
+        if (ast)
+            m_id_type = CompilerType(ast, ast->ObjCBuiltinIdTy);
+        if (valobj_sp->GetProcessSP())
+            m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize();
+    }
+}
+
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp) :
+NSArrayMSyntheticFrontEnd(valobj_sp),
+m_data_32(NULL),
+m_data_64(NULL)
+{
+}
+
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp) :
+NSArrayMSyntheticFrontEnd(valobj_sp),
+m_data_32(NULL),
+m_data_64(NULL)
+{
+}
+
+size_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren ()
+{
+    return GetUsedCount();
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+    if (idx >= CalculateNumChildren())
+        return lldb::ValueObjectSP();
+    lldb::addr_t object_at_idx = GetDataAddress();
+    size_t pyhs_idx = idx;
+    pyhs_idx += GetOffset();
+    if (GetSize() <= pyhs_idx)
+        pyhs_idx -= GetSize();
+    object_at_idx += (pyhs_idx * m_ptr_size);
+    StreamString idx_name;
+    idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+    lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(),
+                                                                 object_at_idx,
+                                                                 m_exe_ctx_ref,
+                                                                 m_id_type);
+    m_children.push_back(retval_sp);
+    return retval_sp;
+}
+
+bool
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::Update()
+{
+    m_children.clear();
+    ValueObjectSP valobj_sp = m_backend.GetSP();
+    m_ptr_size = 0;
+    delete m_data_32;
+    m_data_32 = NULL;
+    delete m_data_64;
+    m_data_64 = NULL;
+    if (!valobj_sp)
+        return false;
+    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+    Error error;
+    error.Clear();
+    lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+    if (!process_sp)
+        return false;
+    m_ptr_size = process_sp->GetAddressByteSize();
+    uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + 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 false;
+    return false;
+}
+
+bool
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::Update()
+{
+    m_children.clear();
+    ValueObjectSP valobj_sp = m_backend.GetSP();
+    m_ptr_size = 0;
+    delete m_data_32;
+    m_data_32 = NULL;
+    delete m_data_64;
+    m_data_64 = NULL;
+    if (!valobj_sp)
+        return false;
+    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+    Error error;
+    error.Clear();
+    lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+    if (!process_sp)
+        return false;
+    m_ptr_size = process_sp->GetAddressByteSize();
+    uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + 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 false;
+    return false;
+}
+
+bool
+lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+size_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd::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;
+}
+
+lldb::addr_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetDataAddress ()
+{
+    if (!m_data_32 && !m_data_64)
+        return LLDB_INVALID_ADDRESS;
+    return m_data_32 ? m_data_32->_data :
+    m_data_64->_data;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetUsedCount ()
+{
+    if (!m_data_32 && !m_data_64)
+        return 0;
+    return m_data_32 ? m_data_32->_used :
+    m_data_64->_used;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetOffset ()
+{
+    if (!m_data_32 && !m_data_64)
+        return 0;
+    return m_data_32 ? m_data_32->_offset :
+    m_data_64->_offset;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetSize ()
+{
+    if (!m_data_32 && !m_data_64)
+        return 0;
+    return m_data_32 ? m_data_32->_size :
+    m_data_64->_size;
+}
+
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::~NSArrayMSyntheticFrontEnd_109 ()
+{
+    delete m_data_32;
+    m_data_32 = NULL;
+    delete m_data_64;
+    m_data_64 = NULL;
+}
+
+lldb::addr_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetDataAddress ()
+{
+    if (!m_data_32 && !m_data_64)
+        return LLDB_INVALID_ADDRESS;
+    return m_data_32 ? m_data_32->_data :
+    m_data_64->_data;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetUsedCount ()
+{
+    if (!m_data_32 && !m_data_64)
+        return 0;
+    return m_data_32 ? m_data_32->_used :
+    m_data_64->_used;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetOffset ()
+{
+    if (!m_data_32 && !m_data_64)
+        return 0;
+    return m_data_32 ? m_data_32->_offset :
+    m_data_64->_offset;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetSize ()
+{
+    if (!m_data_32 && !m_data_64)
+        return 0;
+    return m_data_32 ? m_data_32->_size :
+    m_data_64->_size;
+}
+
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::~NSArrayMSyntheticFrontEnd_1010 ()
+{
+    delete m_data_32;
+    m_data_32 = NULL;
+    delete m_data_64;
+    m_data_64 = NULL;
+}
+
+lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+    SyntheticChildrenFrontEnd (*valobj_sp.get()),
+    m_exe_ctx_ref (),
+    m_ptr_size (8),
+    m_items (0),
+    m_data_ptr (0)
+{
+    if (valobj_sp)
+    {
+        CompilerType type = valobj_sp->GetCompilerType();
+        if (type)
+        {
+            ClangASTContext *ast = valobj_sp->GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext();
+            if (ast)
+                m_id_type = CompilerType(ast->getASTContext(), ast->getASTContext()->ObjCBuiltinIdTy);
+        }
+    }
+}
+
+lldb_private::formatters::NSArrayISyntheticFrontEnd::~NSArrayISyntheticFrontEnd ()
+{
+}
+
+size_t
+lldb_private::formatters::NSArrayISyntheticFrontEnd::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;
+}
+
+size_t
+lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren ()
+{
+    return m_items;
+}
+
+bool
+lldb_private::formatters::NSArrayISyntheticFrontEnd::Update()
+{
+    m_ptr_size = 0;
+    m_items = 0;
+    m_data_ptr = 0;
+    m_children.clear();
+    ValueObjectSP valobj_sp = m_backend.GetSP();
+    if (!valobj_sp)
+        return false;
+    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+    Error error;
+    error.Clear();
+    lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+    if (!process_sp)
+        return false;
+    m_ptr_size = process_sp->GetAddressByteSize();
+    uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
+    m_items = process_sp->ReadPointerFromMemory(data_location, error);
+    if (error.Fail())
+        return false;
+    m_data_ptr = data_location+m_ptr_size;
+    return false;
+}
+
+bool
+lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+    if (idx >= CalculateNumChildren())
+        return lldb::ValueObjectSP();
+    lldb::addr_t object_at_idx = m_data_ptr;
+    object_at_idx += (idx * m_ptr_size);
+    ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
+    if (!process_sp)
+        return lldb::ValueObjectSP();
+    Error error;
+    if (error.Fail())
+        return lldb::ValueObjectSP();
+    StreamString idx_name;
+    idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+    lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(),
+                                                                 object_at_idx,
+                                                                 m_exe_ctx_ref,
+                                                                 m_id_type);
+    m_children.push_back(retval_sp);
+    return retval_sp;
+}
+
+SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+    if (!valobj_sp)
+        return nullptr;
+    
+    lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
+    if (!process_sp)
+        return NULL;
+    AppleObjCRuntime *runtime = (AppleObjCRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    if (!runtime)
+        return NULL;
+    
+    CompilerType valobj_type(valobj_sp->GetCompilerType());
+    Flags flags(valobj_type.GetTypeInfo());
+    
+    if (flags.IsClear(eTypeIsPointer))
+    {
+        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 (!class_name || !*class_name)
+        return NULL;
+    
+    if (!strcmp(class_name,"__NSArrayI"))
+    {
+        return (new NSArrayISyntheticFrontEnd(valobj_sp));
+    }
+    else if (!strcmp(class_name,"__NSArrayM"))
+    {
+        if (runtime->GetFoundationVersion() >= 1100)
+            return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp));
+        else
+            return (new NSArrayMSyntheticFrontEnd_109(valobj_sp));
+    }
+    else
+    {
+        return (new NSArrayCodeRunningSyntheticFrontEnd(valobj_sp));
+    }
+}
+
+lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get())
+{}
+
+size_t
+lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::CalculateNumChildren ()
+{
+    uint64_t count = 0;
+    if (ExtractValueFromObjCExpression(m_backend, "int", "count", count))
+        return count;
+    return 0;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+    StreamString idx_name;
+    idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+    lldb::ValueObjectSP valobj_sp = CallSelectorOnObject(m_backend,"id","objectAtIndex:",idx);
+    if (valobj_sp)
+        valobj_sp->SetName(ConstString(idx_name.GetData()));
+    return valobj_sp;
+}
+
+bool
+lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::Update()
+{
+    return false;
+}
+
+bool
+lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+size_t
+lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+    return 0;
+}
+
+lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::~NSArrayCodeRunningSyntheticFrontEnd ()
+{}
diff --git a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
new file mode 100644
index 0000000..4820c34
--- /dev/null
+++ b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
@@ -0,0 +1,703 @@
+//===-- NSDictionary.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Cocoa.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/DataFormatters/FormattersHelpers.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Target.h"
+
+#include "clang/AST/DeclCXX.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+static CompilerType
+GetLLDBNSPairType (TargetSP target_sp)
+{
+    CompilerType clang_type;
+
+    ClangASTContext *target_ast_context = target_sp->GetScratchClangASTContext();
+
+    if (target_ast_context)
+    {
+        ConstString g___lldb_autogen_nspair("__lldb_autogen_nspair");
+
+        clang_type = target_ast_context->GetTypeForIdentifier<clang::CXXRecordDecl>(g___lldb_autogen_nspair);
+        
+        if (!clang_type)
+        {
+            clang_type = target_ast_context->CreateRecordType(NULL, lldb::eAccessPublic, g___lldb_autogen_nspair.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC);
+            
+            if (clang_type)
+            {
+                ClangASTContext::StartTagDeclarationDefinition(clang_type);
+                CompilerType id_clang_type = target_ast_context->GetBasicType (eBasicTypeObjCID);
+                ClangASTContext::AddFieldToRecordType(clang_type, "key", id_clang_type, lldb::eAccessPublic, 0);
+                ClangASTContext::AddFieldToRecordType(clang_type, "value", id_clang_type, lldb::eAccessPublic, 0);
+                ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
+            }
+        }
+    }
+    return clang_type;
+}
+
+namespace lldb_private {
+    namespace  formatters {
+        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 size_t
+            CalculateNumChildren ();
+            
+            virtual lldb::ValueObjectSP
+            GetChildAtIndex (size_t idx);
+            
+            virtual bool
+            Update();
+            
+            virtual bool
+            MightHaveChildren ();
+            
+            virtual size_t
+            GetIndexOfChildWithName (const ConstString &name);
+            
+            virtual
+            ~NSDictionaryISyntheticFrontEnd ();
+        private:
+            ExecutionContextRef m_exe_ctx_ref;
+            uint8_t m_ptr_size;
+            lldb::ByteOrder m_order;
+            DataDescriptor_32 *m_data_32;
+            DataDescriptor_64 *m_data_64;
+            lldb::addr_t m_data_ptr;
+            CompilerType m_pair_type;
+            std::vector<DictionaryItemDescriptor> 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 size_t
+            CalculateNumChildren ();
+            
+            virtual lldb::ValueObjectSP
+            GetChildAtIndex (size_t idx);
+            
+            virtual bool
+            Update();
+            
+            virtual bool
+            MightHaveChildren ();
+            
+            virtual size_t
+            GetIndexOfChildWithName (const ConstString &name);
+            
+            virtual
+            ~NSDictionaryMSyntheticFrontEnd ();
+        private:
+            ExecutionContextRef m_exe_ctx_ref;
+            uint8_t m_ptr_size;
+            lldb::ByteOrder m_order;
+            DataDescriptor_32 *m_data_32;
+            DataDescriptor_64 *m_data_64;
+            CompilerType m_pair_type;
+            std::vector<DictionaryItemDescriptor> m_children;
+        };
+        
+        class NSDictionaryCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+        {
+        public:
+            NSDictionaryCodeRunningSyntheticFrontEnd (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
+            ~NSDictionaryCodeRunningSyntheticFrontEnd ();
+        };
+    }
+}
+
+template<bool name_entries>
+bool
+lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    bool is_64bit = (ptr_size == 8);
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    uint64_t value = 0;
+    
+    const char* class_name = descriptor->GetClassName().GetCString();
+    
+    if (!class_name || !*class_name)
+        return false;
+    
+    if (!strcmp(class_name,"__NSDictionaryI"))
+    {
+        Error error;
+        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
+        if (error.Fail())
+            return false;
+        value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
+    }
+    else if (!strcmp(class_name,"__NSDictionaryM"))
+    {
+        Error error;
+        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
+        if (error.Fail())
+            return false;
+        value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
+    }
+    /*else if (!strcmp(class_name,"__NSCFDictionary"))
+    {
+        Error error;
+        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error);
+        if (error.Fail())
+            return false;
+        if (is_64bit)
+            value &= ~0x0f1f000000000000UL;
+    }*/
+    else
+    {
+        if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
+            return false;
+    }
+    
+    stream.Printf("%s%" PRIu64 " %s%s",
+                  (name_entries ? "@\"" : ""),
+                  value,
+                  (name_entries ? (value == 1 ? "entry" : "entries") : (value == 1 ? "key/value pair" : "key/value pairs")),
+                  (name_entries ? "\"" : ""));
+    return true;
+}
+
+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 (!class_name || !*class_name)
+        return NULL;
+    
+    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())
+{}
+
+size_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 (size_t idx)
+{
+    StreamString idx_name;
+    idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+    StreamString key_fetcher_expr;
+    key_fetcher_expr.Printf("(id)[(NSArray*)[(id)0x%" PRIx64 " allKeys] objectAtIndex:%" PRIu64 "]", m_backend.GetPointerValue(), (uint64_t)idx);
+    StreamString value_fetcher_expr;
+    value_fetcher_expr.Printf("(id)[(id)0x%" PRIx64 " objectForKey:(%s)]",m_backend.GetPointerValue(),key_fetcher_expr.GetData());
+    StreamString object_fetcher_expr;
+    object_fetcher_expr.Printf("struct __lldb_autogen_nspair { 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;
+    EvaluateExpressionOptions options;
+    options.SetKeepInMemory(true);
+    m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(),
+                                                GetViableFrame(m_backend.GetTargetSP().get()),
+                                                child_sp,
+                                                options);
+    if (child_sp)
+        child_sp->SetName(ConstString(idx_name.GetData()));
+    return child_sp;
+}
+
+bool
+lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::Update()
+{
+    return false;
+}
+
+bool
+lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+size_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_order(lldb::eByteOrderInvalid),
+m_data_32(NULL),
+m_data_64(NULL),
+m_pair_type()
+{
+}
+
+lldb_private::formatters::NSDictionaryISyntheticFrontEnd::~NSDictionaryISyntheticFrontEnd ()
+{
+    delete m_data_32;
+    m_data_32 = NULL;
+    delete m_data_64;
+    m_data_64 = NULL;
+}
+
+size_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;
+}
+
+size_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();
+    delete m_data_32;
+    m_data_32 = NULL;
+    delete m_data_64;
+    m_data_64 = NULL;
+    m_ptr_size = 0;
+    ValueObjectSP valobj_sp = m_backend.GetSP();
+    if (!valobj_sp)
+        return false;
+    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+    Error error;
+    error.Clear();
+    lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+    if (!process_sp)
+        return false;
+    m_ptr_size = process_sp->GetAddressByteSize();
+    m_order = process_sp->GetByteOrder();
+    uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + 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 false;
+    m_data_ptr = data_location + m_ptr_size;
+    return false;
+}
+
+bool
+lldb_private::formatters::NSDictionaryISyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex (size_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)
+    {
+        if (!m_pair_type.IsValid())
+        {
+            TargetSP target_sp(m_backend.GetTargetSP());
+            if (!target_sp)
+                return ValueObjectSP();
+            m_pair_type = GetLLDBNSPairType(target_sp);
+        }
+        if (!m_pair_type.IsValid())
+            return ValueObjectSP();
+        
+        DataBufferSP buffer_sp(new DataBufferHeap(2*m_ptr_size,0));
+        
+        if (m_ptr_size == 8)
+        {
+            uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
+            *data_ptr = dict_item.key_ptr;
+            *(data_ptr+1) = dict_item.val_ptr;
+        }
+        else
+        {
+            uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
+            *data_ptr = dict_item.key_ptr;
+            *(data_ptr+1) = dict_item.val_ptr;
+        }
+        
+        StreamString idx_name;
+        idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+        DataExtractor data(buffer_sp, m_order, m_ptr_size);
+        dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(),
+                                                        data,
+                                                        m_exe_ctx_ref,
+                                                        m_pair_type);
+    }
+    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_order(lldb::eByteOrderInvalid),
+m_data_32(NULL),
+m_data_64(NULL),
+m_pair_type()
+{
+}
+
+lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd ()
+{
+    delete m_data_32;
+    m_data_32 = NULL;
+    delete m_data_64;
+    m_data_64 = NULL;
+}
+
+size_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;
+}
+
+size_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();
+    ValueObjectSP valobj_sp = m_backend.GetSP();
+    m_ptr_size = 0;
+    delete m_data_32;
+    m_data_32 = NULL;
+    delete m_data_64;
+    m_data_64 = NULL;
+    if (!valobj_sp)
+        return false;
+    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+    Error error;
+    error.Clear();
+    lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+    if (!process_sp)
+        return false;
+    m_ptr_size = process_sp->GetAddressByteSize();
+    m_order = process_sp->GetByteOrder();
+    uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + 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 false;
+    return false;
+}
+
+bool
+lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex (size_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)
+    {
+        if (!m_pair_type.IsValid())
+        {
+            TargetSP target_sp(m_backend.GetTargetSP());
+            if (!target_sp)
+                return ValueObjectSP();
+            m_pair_type = GetLLDBNSPairType(target_sp);
+        }
+        if (!m_pair_type.IsValid())
+            return ValueObjectSP();
+        
+        DataBufferSP buffer_sp(new DataBufferHeap(2*m_ptr_size,0));
+        
+        if (m_ptr_size == 8)
+        {
+            uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
+            *data_ptr = dict_item.key_ptr;
+            *(data_ptr+1) = dict_item.val_ptr;
+        }
+        else
+        {
+            uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
+            *data_ptr = dict_item.key_ptr;
+            *(data_ptr+1) = dict_item.val_ptr;
+        }
+        
+        StreamString idx_name;
+        idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+        DataExtractor data(buffer_sp, m_order, m_ptr_size);
+        dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(),
+                                                        data,
+                                                        m_exe_ctx_ref,
+                                                        m_pair_type);
+    }
+    return dict_item.valobj_sp;
+}
+
+template bool
+lldb_private::formatters::NSDictionarySummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+
+template bool
+lldb_private::formatters::NSDictionarySummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
diff --git a/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp b/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
new file mode 100644
index 0000000..4e2c066
--- /dev/null
+++ b/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
@@ -0,0 +1,341 @@
+//===-- NSIndexPath.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Cocoa.h"
+
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Symbol/ClangASTContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+class NSIndexPathSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+{
+public:
+    NSIndexPathSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+    SyntheticChildrenFrontEnd (*valobj_sp.get()),
+    m_ptr_size(0),
+    m_uint_star_type()
+    {
+        m_ptr_size = m_backend.GetTargetSP()->GetArchitecture().GetAddressByteSize();
+    }
+    
+    virtual size_t
+    CalculateNumChildren ()
+    {
+        return m_impl.GetNumIndexes();
+    }
+    
+    virtual lldb::ValueObjectSP
+    GetChildAtIndex (size_t idx)
+    {
+        return m_impl.GetIndexAtIndex(idx, m_uint_star_type);
+    }
+    
+    virtual bool
+    Update()
+    {
+        m_impl.Clear();
+        
+        TypeSystem* type_system = m_backend.GetCompilerType().GetTypeSystem();
+        if (!type_system)
+            return false;
+
+        ClangASTContext *ast = m_backend.GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext();
+        if (!ast)
+            return false;
+
+        m_uint_star_type = ast->GetPointerSizedIntType(false);
+        
+        static ConstString g__indexes("_indexes");
+        static ConstString g__length("_length");
+
+        ProcessSP process_sp = m_backend.GetProcessSP();
+        if (!process_sp)
+            return false;
+        
+        ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+        
+        if (!runtime)
+            return false;
+        
+        ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(m_backend));
+        
+        if (!descriptor.get() || !descriptor->IsValid())
+            return false;
+        
+        uint64_t info_bits(0),value_bits(0),payload(0);
+        
+        if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits, &payload))
+        {
+            m_impl.m_inlined.SetIndexes(payload, *process_sp);
+            m_impl.m_mode = Mode::Inlined;
+        }
+        else
+        {
+            ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _indexes_id;
+            ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _length_id;
+            
+            bool has_indexes(false),has_length(false);
+            
+            for (size_t x = 0;
+                 x < descriptor->GetNumIVars();
+                 x++)
+            {
+                const auto& ivar = descriptor->GetIVarAtIndex(x);
+                if (ivar.m_name == g__indexes)
+                {
+                    _indexes_id = ivar;
+                    has_indexes = true;
+                }
+                else if (ivar.m_name == g__length)
+                {
+                    _length_id = ivar;
+                    has_length = true;
+                }
+                
+                if (has_length && has_indexes)
+                    break;
+            }
+            
+            if (has_length && has_indexes)
+            {
+                m_impl.m_outsourced.m_indexes = m_backend.GetSyntheticChildAtOffset(_indexes_id.m_offset,
+                                                                                    m_uint_star_type.GetPointerType(),
+                                                                                    true).get();
+                ValueObjectSP length_sp(m_backend.GetSyntheticChildAtOffset(_length_id.m_offset,
+                                                                            m_uint_star_type,
+                                                                            true));
+                if (length_sp)
+                {
+                    m_impl.m_outsourced.m_count = length_sp->GetValueAsUnsigned(0);
+                    if (m_impl.m_outsourced.m_indexes)
+                        m_impl.m_mode = Mode::Outsourced;
+                }
+            }
+        }
+        return false;
+    }
+    
+    virtual bool
+    MightHaveChildren ()
+    {
+        if (m_impl.m_mode == Mode::Invalid)
+            return false;
+        return true;
+    }
+    
+    virtual size_t
+    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;
+    }
+    
+    virtual lldb::ValueObjectSP
+    GetSyntheticValue () { return nullptr; }
+    
+    virtual
+    ~NSIndexPathSyntheticFrontEnd () {}
+    
+protected:
+    ObjCLanguageRuntime::ClassDescriptorSP m_descriptor_sp;
+    
+    enum class Mode {
+        Inlined,
+        Outsourced,
+        Invalid
+    };
+    
+    struct Impl {
+        Mode m_mode;
+
+        size_t
+        GetNumIndexes ()
+        {
+            switch (m_mode)
+            {
+                case Mode::Inlined:
+                    return m_inlined.GetNumIndexes();
+                case Mode::Outsourced:
+                    return m_outsourced.m_count;
+                default:
+                    return 0;
+            }
+        }
+        
+        lldb::ValueObjectSP
+        GetIndexAtIndex (size_t idx, const CompilerType& desired_type)
+        {
+            if (idx >= GetNumIndexes())
+                return nullptr;
+            switch (m_mode)
+            {
+                default: return nullptr;
+                case Mode::Inlined:
+                    return m_inlined.GetIndexAtIndex (idx, desired_type);
+                case Mode::Outsourced:
+                    return m_outsourced.GetIndexAtIndex (idx);
+            }
+        }
+
+        struct InlinedIndexes {
+        public:
+          void SetIndexes(uint64_t value, Process& p)
+          {
+              m_indexes = value;
+              _lengthForInlinePayload(p.GetAddressByteSize());
+              m_process = &p;
+          }
+              
+          size_t
+          GetNumIndexes ()
+          {
+              return m_count;
+          }
+
+          lldb::ValueObjectSP
+          GetIndexAtIndex (size_t idx, const CompilerType& desired_type)
+          {
+              std::pair<uint64_t, bool> value(_indexAtPositionForInlinePayload(idx));
+              if (!value.second)
+                  return nullptr;
+              
+              Value v;
+              if (m_ptr_size == 8)
+              {
+                  Scalar scalar( (unsigned long long)value.first );
+                  v = Value(scalar);
+              }
+              else
+              {
+                  Scalar scalar( (unsigned int)value.first );
+                  v = Value(scalar);
+              }
+
+              v.SetCompilerType(desired_type);
+
+              StreamString idx_name;
+              idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+
+              return ValueObjectConstResult::Create(m_process, v, ConstString(idx_name.GetData()));
+          }
+            
+            void
+            Clear ()
+            {
+                m_indexes = 0;
+                m_count = 0;
+                m_ptr_size = 0;
+                m_process = nullptr;
+            }
+                    
+          private:
+          uint64_t m_indexes;
+          size_t m_count;
+          uint32_t m_ptr_size;
+          Process *m_process;
+                    
+          // cfr. Foundation for the details of this code
+          size_t _lengthForInlinePayload(uint32_t ptr_size) {
+              m_ptr_size = ptr_size;
+              if (m_ptr_size == 8)
+              m_count = ((m_indexes >> 3) & 0x7);
+              else
+              m_count = ((m_indexes >> 3) & 0x3);
+              return m_count;
+          }
+                    
+          std::pair<uint64_t, bool>
+          _indexAtPositionForInlinePayload(size_t pos)
+          {
+              if (m_ptr_size == 8)
+              {
+                switch (pos) {
+                    case 5: return {((m_indexes >> 51) & 0x1ff),true};
+                    case 4: return {((m_indexes >> 42) & 0x1ff),true};
+                    case 3: return {((m_indexes >> 33) & 0x1ff),true};
+                    case 2: return {((m_indexes >> 24) & 0x1ff),true};
+                    case 1: return {((m_indexes >> 15) & 0x1ff),true};
+                    case 0: return {((m_indexes >>  6) & 0x1ff),true};
+                }
+              }
+              else
+                  {
+                  switch (pos) {
+                      case 2: return {((m_indexes >> 23) & 0x1ff),true};
+                      case 1: return {((m_indexes >> 14) & 0x1ff),true};
+                      case 0: return {((m_indexes >>  5) & 0x1ff),true};
+                  }
+              }
+              return {0,false};
+          }
+
+        };
+        struct OutsourcedIndexes {
+            ValueObject *m_indexes;
+            size_t m_count;
+                    
+            lldb::ValueObjectSP
+            GetIndexAtIndex (size_t idx)
+            {
+                if (m_indexes)
+                {
+                    ValueObjectSP index_sp(m_indexes->GetSyntheticArrayMember(idx, true));
+                    return index_sp;
+                }
+                return nullptr;
+            }
+            
+            void
+            Clear ()
+            {
+                m_indexes = nullptr;
+                m_count = 0;
+            }
+        };
+
+        union {
+            struct InlinedIndexes m_inlined;
+            struct OutsourcedIndexes m_outsourced;
+        };
+        
+        void
+        Clear ()
+        {
+            m_mode = Mode::Invalid;
+            m_inlined.Clear();
+            m_outsourced.Clear();
+        }
+    } m_impl;
+    
+    uint32_t m_ptr_size;
+    CompilerType m_uint_star_type;
+};
+
+namespace lldb_private {
+    namespace formatters {
+        
+        SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+        {
+            if (valobj_sp)
+                return new NSIndexPathSyntheticFrontEnd(valobj_sp);
+            return nullptr;
+        }
+    }
+}
diff --git a/lldb/source/Plugins/Language/ObjC/NSSet.cpp b/lldb/source/Plugins/Language/ObjC/NSSet.cpp
new file mode 100644
index 0000000..113e05d
--- /dev/null
+++ b/lldb/source/Plugins/Language/ObjC/NSSet.cpp
@@ -0,0 +1,718 @@
+//===-- NSSet.cpp ------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Cocoa.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/DataFormatters/FormattersHelpers.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;
+
+namespace lldb_private {
+    namespace formatters {
+        class NSSetISyntheticFrontEnd : 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 SetItemDescriptor
+            {
+                lldb::addr_t item_ptr;
+                lldb::ValueObjectSP valobj_sp;
+            };
+            
+        public:
+            NSSetISyntheticFrontEnd (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
+            ~NSSetISyntheticFrontEnd ();
+        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<SetItemDescriptor> m_children;
+        };
+        
+        class NSOrderedSetSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+        {
+        private:
+            
+        public:
+            NSOrderedSetSyntheticFrontEnd (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
+            ~NSOrderedSetSyntheticFrontEnd ();
+        private:
+            uint32_t m_count;
+            std::map<uint32_t,lldb::ValueObjectSP> m_children;
+        };
+        
+        class NSSetMSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+        {
+        private:
+            struct DataDescriptor_32
+            {
+                uint32_t _used : 26;
+                uint32_t _size;
+                uint32_t _mutations;
+                uint32_t _objs_addr;
+            };
+            struct DataDescriptor_64
+            {
+                uint64_t _used : 58;
+                uint64_t _size;
+                uint64_t _mutations;
+                uint64_t _objs_addr;
+            };
+            struct SetItemDescriptor
+            {
+                lldb::addr_t item_ptr;
+                lldb::ValueObjectSP valobj_sp;
+            };
+        public:
+            NSSetMSyntheticFrontEnd (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
+            ~NSSetMSyntheticFrontEnd ();
+        private:
+            ExecutionContextRef m_exe_ctx_ref;
+            uint8_t m_ptr_size;
+            DataDescriptor_32 *m_data_32;
+            DataDescriptor_64 *m_data_64;
+            std::vector<SetItemDescriptor> m_children;
+        };
+        
+        class NSSetCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+        {
+        public:
+            NSSetCodeRunningSyntheticFrontEnd (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
+            ~NSSetCodeRunningSyntheticFrontEnd ();
+        };
+    }
+}
+
+template<bool cf_style>
+bool
+lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    bool is_64bit = (ptr_size == 8);
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    uint64_t value = 0;
+    
+    const char* class_name = descriptor->GetClassName().GetCString();
+    
+    if (!class_name || !*class_name)
+        return false;
+    
+    if (!strcmp(class_name,"__NSSetI"))
+    {
+        Error error;
+        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
+        if (error.Fail())
+            return false;
+        value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
+    }
+    else if (!strcmp(class_name,"__NSSetM"))
+    {
+        Error error;
+        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
+        if (error.Fail())
+            return false;
+        value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
+    }
+    /*else if (!strcmp(class_name,"__NSCFSet"))
+    {
+        Error error;
+        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error);
+        if (error.Fail())
+            return false;
+        if (is_64bit)
+            value &= ~0x1fff000000000000UL;
+    }
+    else if (!strcmp(class_name,"NSCountedSet"))
+    {
+        Error error;
+        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
+        if (error.Fail())
+            return false;
+        value = process_sp->ReadUnsignedIntegerFromMemory(value + (is_64bit ? 20 : 12), 4, 0, error);
+        if (error.Fail())
+            return false;
+        if (is_64bit)
+            value &= ~0x1fff000000000000UL;
+    }*/
+    else
+    {
+        if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
+            return false;
+    }
+    
+    stream.Printf("%s%" PRIu64 " %s%s",
+                  (cf_style ? "@\"" : ""),
+                  value,
+                  (cf_style ? (value == 1 ? "value" : "values") : (value == 1 ? "object" : "objects")),
+                  (cf_style ? "\"" : ""));
+    return true;
+}
+
+SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreator (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 (!class_name || !*class_name)
+        return NULL;
+    
+    if (!strcmp(class_name,"__NSSetI"))
+    {
+        return (new NSSetISyntheticFrontEnd(valobj_sp));
+    }
+    else if (!strcmp(class_name,"__NSSetM"))
+    {
+        return (new NSSetMSyntheticFrontEnd(valobj_sp));
+    }
+    else if ((!strcmp(class_name,"__NSOrderedSetI")) || (!strcmp(class_name,"__NSOrderedSetM")))
+    {
+        return new NSOrderedSetSyntheticFrontEnd(valobj_sp); // this runs code
+    }
+    else
+    {
+        return /*(new NSSetCodeRunningSyntheticFrontEnd(valobj_sp))*/ NULL;
+    }
+}
+
+lldb_private::formatters::NSSetISyntheticFrontEnd::NSSetISyntheticFrontEnd (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)
+        Update();
+}
+
+lldb_private::formatters::NSSetISyntheticFrontEnd::~NSSetISyntheticFrontEnd ()
+{
+    delete m_data_32;
+    m_data_32 = NULL;
+    delete m_data_64;
+    m_data_64 = NULL;
+}
+
+size_t
+lldb_private::formatters::NSSetISyntheticFrontEnd::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;
+}
+
+size_t
+lldb_private::formatters::NSSetISyntheticFrontEnd::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::NSSetISyntheticFrontEnd::Update()
+{
+    m_children.clear();
+    delete m_data_32;
+    m_data_32 = NULL;
+    delete m_data_64;
+    m_data_64 = NULL;
+    m_ptr_size = 0;
+    ValueObjectSP valobj_sp = m_backend.GetSP();
+    if (!valobj_sp)
+        return false;
+    if (!valobj_sp)
+        return false;
+    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 false;
+    }
+    error.Clear();
+    lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+    if (!process_sp)
+        return false;
+    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 false;
+    m_data_ptr = data_location + m_ptr_size;
+    return false;
+}
+
+bool
+lldb_private::formatters::NSSetISyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+    uint32_t num_children = CalculateNumChildren();
+    
+    if (idx >= num_children)
+        return lldb::ValueObjectSP();
+    
+    ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
+    if (!process_sp)
+        return lldb::ValueObjectSP();
+    
+    if (m_children.empty())
+    {
+        // do the scan phase
+        lldb::addr_t obj_at_idx = 0;
+        
+        uint32_t tries = 0;
+        uint32_t test_idx = 0;
+        
+        while(tries < num_children)
+        {
+            obj_at_idx = m_data_ptr + (test_idx * m_ptr_size);
+            if (!process_sp)
+                return lldb::ValueObjectSP();
+            Error error;
+            obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error);
+            if (error.Fail())
+                return lldb::ValueObjectSP();
+            
+            test_idx++;
+            
+            if (!obj_at_idx)
+                continue;
+            tries++;
+            
+            SetItemDescriptor descriptor = {obj_at_idx,lldb::ValueObjectSP()};
+            
+            m_children.push_back(descriptor);
+        }
+    }
+    
+    if (idx >= m_children.size()) // should never happen
+        return lldb::ValueObjectSP();
+    
+    SetItemDescriptor &set_item = m_children[idx];
+    if (!set_item.valobj_sp)
+    {
+        auto ptr_size = process_sp->GetAddressByteSize();
+        DataBufferHeap buffer(ptr_size,0);
+        switch (ptr_size)
+        {
+            case 0: // architecture has no clue?? - fail
+                return lldb::ValueObjectSP();
+            case 4:
+                *((uint32_t*)buffer.GetBytes()) = (uint32_t)set_item.item_ptr;
+                break;
+            case 8:
+                *((uint64_t*)buffer.GetBytes()) = (uint64_t)set_item.item_ptr;
+                break;
+            default:
+                assert(false && "pointer size is not 4 nor 8 - get out of here ASAP");
+        }
+        StreamString idx_name;
+        idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+        
+        DataExtractor data(buffer.GetBytes(),
+                           buffer.GetByteSize(),
+                           process_sp->GetByteOrder(),
+                           process_sp->GetAddressByteSize());
+        
+        set_item.valobj_sp =
+            CreateValueObjectFromData(idx_name.GetData(),
+                                      data,
+                                      m_exe_ctx_ref,
+                                      m_backend.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
+    }
+    return set_item.valobj_sp;
+}
+
+lldb_private::formatters::NSSetMSyntheticFrontEnd::NSSetMSyntheticFrontEnd (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)
+        Update ();
+}
+
+lldb_private::formatters::NSSetMSyntheticFrontEnd::~NSSetMSyntheticFrontEnd ()
+{
+    delete m_data_32;
+    m_data_32 = NULL;
+    delete m_data_64;
+    m_data_64 = NULL;
+}
+
+size_t
+lldb_private::formatters::NSSetMSyntheticFrontEnd::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;
+}
+
+size_t
+lldb_private::formatters::NSSetMSyntheticFrontEnd::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::NSSetMSyntheticFrontEnd::Update()
+{
+    m_children.clear();
+    ValueObjectSP valobj_sp = m_backend.GetSP();
+    m_ptr_size = 0;
+    delete m_data_32;
+    m_data_32 = NULL;
+    delete m_data_64;
+    m_data_64 = NULL;
+    if (!valobj_sp)
+        return false;
+    if (!valobj_sp)
+        return false;
+    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 false;
+    }
+    error.Clear();
+    lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+    if (!process_sp)
+        return false;
+    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 false;
+    return false;
+}
+
+bool
+lldb_private::formatters::NSSetMSyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+    lldb::addr_t m_objs_addr = (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();
+    
+    ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
+    if (!process_sp)
+        return lldb::ValueObjectSP();
+    
+    if (m_children.empty())
+    {
+        // do the scan phase
+        lldb::addr_t obj_at_idx = 0;
+        
+        uint32_t tries = 0;
+        uint32_t test_idx = 0;
+        
+        while(tries < num_children)
+        {
+            obj_at_idx = m_objs_addr + (test_idx * m_ptr_size);
+            if (!process_sp)
+                return lldb::ValueObjectSP();
+            Error error;
+            obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error);
+            if (error.Fail())
+                return lldb::ValueObjectSP();
+            
+            test_idx++;
+            
+            if (!obj_at_idx)
+                continue;
+            tries++;
+            
+            SetItemDescriptor descriptor = {obj_at_idx,lldb::ValueObjectSP()};
+            
+            m_children.push_back(descriptor);
+        }
+    }
+    
+    if (idx >= m_children.size()) // should never happen
+        return lldb::ValueObjectSP();
+    
+    SetItemDescriptor &set_item = m_children[idx];
+    if (!set_item.valobj_sp)
+    {
+        auto ptr_size = process_sp->GetAddressByteSize();
+        DataBufferHeap buffer(ptr_size,0);
+        switch (ptr_size)
+        {
+            case 0: // architecture has no clue?? - fail
+                return lldb::ValueObjectSP();
+            case 4:
+                *((uint32_t*)buffer.GetBytes()) = (uint32_t)set_item.item_ptr;
+                break;
+            case 8:
+                *((uint64_t*)buffer.GetBytes()) = (uint64_t)set_item.item_ptr;
+                break;
+            default:
+                assert(false && "pointer size is not 4 nor 8 - get out of here ASAP");
+        }
+        StreamString idx_name;
+        idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+        
+        DataExtractor data(buffer.GetBytes(),
+                           buffer.GetByteSize(),
+                           process_sp->GetByteOrder(),
+                           process_sp->GetAddressByteSize());
+        
+        set_item.valobj_sp =
+            CreateValueObjectFromData(idx_name.GetData(),
+                                      data,
+                                      m_exe_ctx_ref,
+                                      m_backend.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
+    }
+    return set_item.valobj_sp;
+}
+
+lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::NSOrderedSetSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_count(UINT32_MAX),
+m_children()
+{}
+
+size_t
+lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::CalculateNumChildren ()
+{
+    if (m_count != UINT32_MAX)
+        return m_count;
+    uint64_t count_temp;
+    if (ExtractValueFromObjCExpression(m_backend,"unsigned int","count",count_temp))
+        return (m_count = count_temp);
+    return (m_count = 0);
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+    auto iter = m_children.find(idx);
+    if (iter == m_children.end())
+    {
+        lldb::ValueObjectSP retval_sp;
+        if (idx <= m_count)
+        {
+            retval_sp = CallSelectorOnObject(m_backend, "id", "objectAtIndex", idx);
+            if (retval_sp)
+            {
+                StreamString idx_name;
+                idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+                retval_sp->SetName(ConstString(idx_name.GetData()));
+            }
+            m_children[idx] = retval_sp;
+        }
+        return retval_sp;
+    }
+    else
+        return iter->second;
+}
+
+bool
+lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::Update()
+{
+    return false;
+}
+
+bool
+lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::MightHaveChildren ()
+{
+    return true;
+}
+
+size_t
+lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::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;
+}
+
+lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::~NSOrderedSetSyntheticFrontEnd ()
+{
+}
+
+template bool
+lldb_private::formatters::NSSetSummaryProvider<true> (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+template bool
+lldb_private::formatters::NSSetSummaryProvider<false> (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
index d6a68af..003a467 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -13,11 +13,18 @@
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/StreamString.h"
 #include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
 #include "lldb/Symbol/CompilerType.h"
 #include "lldb/Target/ObjCLanguageRuntime.h"
 
+#include "CF.h"
+#include "Cocoa.h"
+#include "CoreMedia.h"
+
 using namespace lldb;
 using namespace lldb_private;
+using namespace lldb_private::formatters;
 
 void
 ObjCLanguage::Initialize()
@@ -302,6 +309,318 @@
     return names.size();
 }
 
+static void
+LoadObjCFormatters(TypeCategoryImplSP objc_category_sp)
+{
+    if (!objc_category_sp)
+        return;
+    
+    TypeSummaryImpl::Flags objc_flags;
+    objc_flags.SetCascades(false)
+    .SetSkipPointers(true)
+    .SetSkipReferences(true)
+    .SetDontShowChildren(true)
+    .SetDontShowValue(true)
+    .SetShowMembersOneLiner(false)
+    .SetHideItemNames(false);
+    
+    lldb::TypeSummaryImplSP ObjC_BOOL_summary(new CXXFunctionSummaryFormat(objc_flags, lldb_private::formatters::ObjCBOOLSummaryProvider,""));
+    objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL"),
+                                                       ObjC_BOOL_summary);
+    objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL &"),
+                                                       ObjC_BOOL_summary);
+    objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL *"),
+                                                       ObjC_BOOL_summary);
+    
+#ifndef LLDB_DISABLE_PYTHON
+    // we need to skip pointers here since we are special casing a SEL* when retrieving its value
+    objc_flags.SetSkipPointers(true);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, "SEL summary provider", ConstString("SEL"), objc_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, "SEL summary provider", ConstString("struct objc_selector"), objc_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, "SEL summary provider", ConstString("objc_selector"), objc_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<true>, "SEL summary provider", ConstString("objc_selector *"), objc_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<true>, "SEL summary provider", ConstString("SEL *"), objc_flags);
+    
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCClassSummaryProvider, "Class summary provider", ConstString("Class"), objc_flags);
+    
+    SyntheticChildren::Flags class_synth_flags;
+    class_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
+    
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::ObjCClassSyntheticFrontEndCreator, "Class synthetic children", ConstString("Class"), class_synth_flags);
+#endif // LLDB_DISABLE_PYTHON
+    
+    objc_flags.SetSkipPointers(false);
+    objc_flags.SetCascades(true);
+    objc_flags.SetSkipReferences(false);
+    
+    AddStringSummary (objc_category_sp,
+                      "${var.__FuncPtr%A}",
+                      ConstString("__block_literal_generic"),
+                      objc_flags);
+    
+    AddStringSummary(objc_category_sp,
+                     "${var.years} years, ${var.months} months, ${var.days} days, ${var.hours} hours, ${var.minutes} minutes ${var.seconds} seconds",
+                     ConstString("CFGregorianUnits"),
+                     objc_flags);
+    AddStringSummary(objc_category_sp,
+                     "location=${var.location} length=${var.length}",
+                     ConstString("CFRange"),
+                     objc_flags);
+    
+    AddStringSummary(objc_category_sp,
+                     "location=${var.location}, length=${var.length}",
+                     ConstString("NSRange"),
+                     objc_flags);
+    AddStringSummary(objc_category_sp,
+                     "(${var.origin}, ${var.size}), ...",
+                     ConstString("NSRectArray"),
+                     objc_flags);
+    
+    AddOneLineSummary (objc_category_sp,
+                       ConstString("NSPoint"),
+                       objc_flags);
+    AddOneLineSummary (objc_category_sp,
+                       ConstString("NSSize"),
+                       objc_flags);
+    AddOneLineSummary (objc_category_sp,
+                       ConstString("NSRect"),
+                       objc_flags);
+    
+    AddOneLineSummary (objc_category_sp,
+                       ConstString("CGSize"),
+                       objc_flags);
+    AddOneLineSummary (objc_category_sp,
+                       ConstString("CGPoint"),
+                       objc_flags);
+    AddOneLineSummary (objc_category_sp,
+                       ConstString("CGRect"),
+                       objc_flags);
+    
+    AddStringSummary(objc_category_sp,
+                     "red=${var.red} green=${var.green} blue=${var.blue}",
+                     ConstString("RGBColor"),
+                     objc_flags);
+    AddStringSummary(objc_category_sp,
+                     "(t=${var.top}, l=${var.left}, b=${var.bottom}, r=${var.right})",
+                     ConstString("Rect"),
+                     objc_flags);
+    AddStringSummary(objc_category_sp,
+                     "(v=${var.v}, h=${var.h})",
+                     ConstString("Point"),
+                     objc_flags);
+    AddStringSummary(objc_category_sp,
+                     "${var.month}/${var.day}/${var.year}  ${var.hour} :${var.minute} :${var.second} dayOfWeek:${var.dayOfWeek}",
+                     ConstString("DateTimeRect *"),
+                     objc_flags);
+    AddStringSummary(objc_category_sp,
+                     "${var.ld.month}/${var.ld.day}/${var.ld.year} ${var.ld.hour} :${var.ld.minute} :${var.ld.second} dayOfWeek:${var.ld.dayOfWeek}",
+                     ConstString("LongDateRect"),
+                     objc_flags);
+    AddStringSummary(objc_category_sp,
+                     "(x=${var.x}, y=${var.y})",
+                     ConstString("HIPoint"),
+                     objc_flags);
+    AddStringSummary(objc_category_sp,
+                     "origin=${var.origin} size=${var.size}",
+                     ConstString("HIRect"),
+                     objc_flags);
+    
+    TypeSummaryImpl::Flags appkit_flags;
+    appkit_flags.SetCascades(true)
+    .SetSkipPointers(false)
+    .SetSkipReferences(false)
+    .SetDontShowChildren(true)
+    .SetDontShowValue(false)
+    .SetShowMembersOneLiner(false)
+    .SetHideItemNames(false);
+    
+    appkit_flags.SetDontShowChildren(false);
+    
+    
+#ifndef LLDB_DISABLE_PYTHON
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("NSArray"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("NSMutableArray"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSArrayI"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSArrayM"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSCFArray"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFArrayRef"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFMutableArrayRef"), appkit_flags);
+    
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("NSDictionary"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("NSMutableDictionary"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSCFDictionary"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSDictionaryI"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSDictionaryM"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<true>, "NSDictionary summary provider", ConstString("CFDictionaryRef"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<true>, "NSDictionary summary provider", ConstString("CFMutableDictionaryRef"), appkit_flags);
+    
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSSet summary", ConstString("NSSet"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>, "CFSetRef summary", ConstString("CFSetRef"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>, "CFMutableSetRef summary", ConstString("CFMutableSetRef"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSCFSet summary", ConstString("__NSCFSet"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSSetI summary", ConstString("__NSSetI"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSSetM summary", ConstString("__NSSetM"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSCountedSet summary", ConstString("NSCountedSet"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSOrderedSet summary", ConstString("NSOrderedSet"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSOrderedSetI summary", ConstString("__NSOrderedSetI"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSOrderedSetM summary", ConstString("__NSOrderedSetM"), appkit_flags);
+    
+    // AddSummary(appkit_category_sp, "${var.key%@} -> ${var.value%@}", ConstString("$_lldb_typegen_nspair"), appkit_flags);
+    
+    appkit_flags.SetDontShowChildren(true);
+    
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSArrayM"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSArrayI"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("NSArray"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("NSMutableArray"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSCFArray"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("CFMutableArrayRef"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("CFArrayRef"), ScriptedSyntheticChildren::Flags());
+    
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSDictionaryM"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSDictionaryI"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSCFDictionary"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("NSDictionary"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("NSMutableDictionary"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFDictionaryRef"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFMutableDictionaryRef"), ScriptedSyntheticChildren::Flags());
+    
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSSet synthetic children", ConstString("NSSet"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSSetI synthetic children", ConstString("__NSSetI"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSSetM synthetic children", ConstString("__NSSetM"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSMutableSet synthetic children", ConstString("NSMutableSet"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSOrderedSet synthetic children", ConstString("NSOrderedSet"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"), ScriptedSyntheticChildren::Flags());
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"), ScriptedSyntheticChildren::Flags());
+    
+    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator, "NSIndexPath synthetic children", ConstString("NSIndexPath"), ScriptedSyntheticChildren::Flags());
+    
+    AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFBagRef"), appkit_flags);
+    AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("__CFBag"), appkit_flags);
+    AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("const struct __CFBag"), appkit_flags);
+    AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFMutableBagRef"), appkit_flags);
+    
+    AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBinaryHeapSummaryProvider, "CFBinaryHeap summary provider", ConstString("CFBinaryHeapRef"), appkit_flags);
+    AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBinaryHeapSummaryProvider, "CFBinaryHeap summary provider", ConstString("__CFBinaryHeap"), appkit_flags);
+    
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSString"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFStringRef"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__CFString"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFMutableStringRef"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSMutableString"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__NSCFConstantString"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__NSCFString"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSCFConstantString"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSCFString"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSPathStore2"), appkit_flags);
+    
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSAttributedStringSummaryProvider, "NSAttributedString summary provider", ConstString("NSAttributedString"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSMutableAttributedStringSummaryProvider, "NSMutableAttributedString summary provider", ConstString("NSMutableAttributedString"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSMutableAttributedStringSummaryProvider, "NSMutableAttributedString summary provider", ConstString("NSConcreteMutableAttributedString"), appkit_flags);
+    
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSBundleSummaryProvider, "NSBundle summary provider", ConstString("NSBundle"), appkit_flags);
+    
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSData"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSConcreteData"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSConcreteMutableData"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSMutableData"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("__NSCFData"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, "NSData summary provider", ConstString("CFDataRef"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, "NSData summary provider", ConstString("CFMutableDataRef"), appkit_flags);
+    
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSMachPortSummaryProvider, "NSMachPort summary provider", ConstString("NSMachPort"), appkit_flags);
+    
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNotificationSummaryProvider, "NSNotification summary provider", ConstString("NSNotification"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNotificationSummaryProvider, "NSNotification summary provider", ConstString("NSConcreteNotification"), appkit_flags);
+    
+    AddStringSummary(objc_category_sp, "domain: ${var._domain} - code: ${var._code}", ConstString("NSError"), appkit_flags);
+    AddStringSummary(objc_category_sp,"name:${var.name%S} reason:${var.reason%S}",ConstString("NSException"),appkit_flags);
+    
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSNumber"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "CFNumberRef summary provider", ConstString("CFNumberRef"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("__NSCFBoolean"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("__NSCFNumber"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSCFBoolean"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSCFNumber"), appkit_flags);
+    
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSDecimalNumber summary provider", ConstString("NSDecimalNumber"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSHost summary provider", ConstString("NSHost"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSTask summary provider", ConstString("NSTask"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSValue summary provider", ConstString("NSValue"), appkit_flags);
+    
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSURLSummaryProvider, "NSURL summary provider", ConstString("NSURL"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSURLSummaryProvider, "NSURL summary provider", ConstString("CFURLRef"), appkit_flags);
+    
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("NSDate"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("__NSDate"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("__NSTaggedDate"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("NSCalendarDate"), appkit_flags);
+    
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("NSTimeZone"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("CFTimeZoneRef"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("__NSTimeZone"), appkit_flags);
+    
+    // CFAbsoluteTime is actually a double rather than a pointer to an object
+    // we do not care about the numeric value, since it is probably meaningless to users
+    appkit_flags.SetDontShowValue(true);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::CFAbsoluteTimeSummaryProvider, "CFAbsoluteTime summary provider", ConstString("CFAbsoluteTime"), appkit_flags);
+    appkit_flags.SetDontShowValue(false);
+    
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, "NSIndexSet summary provider", ConstString("NSIndexSet"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, "NSIndexSet summary provider", ConstString("NSMutableIndexSet"), appkit_flags);
+    
+    AddStringSummary(objc_category_sp,
+                     "@\"${var.month%d}/${var.day%d}/${var.year%d} ${var.hour%d}:${var.minute%d}:${var.second}\"",
+                     ConstString("CFGregorianDate"),
+                     appkit_flags);
+    
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("CFBitVectorRef"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("CFMutableBitVectorRef"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("__CFBitVector"), appkit_flags);
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("__CFMutableBitVector"), appkit_flags);
+#endif // LLDB_DISABLE_PYTHON
+}
+
+static void
+LoadCoreMediaFormatters(TypeCategoryImplSP objc_category_sp)
+{
+    if (!objc_category_sp)
+        return;
+
+    TypeSummaryImpl::Flags cm_flags;
+    cm_flags.SetCascades(true)
+    .SetDontShowChildren(false)
+    .SetDontShowValue(false)
+    .SetHideItemNames(false)
+    .SetShowMembersOneLiner(false)
+    .SetSkipPointers(false)
+    .SetSkipReferences(false);
+    
+#ifndef LLDB_DISABLE_PYTHON
+    AddCXXSummary(objc_category_sp, lldb_private::formatters::CMTimeSummaryProvider, "CMTime summary provider", ConstString("CMTime"), cm_flags);
+#endif // LLDB_DISABLE_PYTHON
+}
+
+
+lldb::TypeCategoryImplSP
+ObjCLanguage::GetFormatters ()
+{
+    static std::once_flag g_initialize;
+    static TypeCategoryImplSP g_category;
+    
+    std::call_once(g_initialize, [this] () -> void {
+        DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
+        if (g_category)
+        {
+            LoadCoreMediaFormatters(g_category);
+            LoadObjCFormatters(g_category);
+        }
+    });
+    return g_category;
+}
+
 std::vector<ConstString>
 ObjCLanguage::GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic)
 {
diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
index 3850c21..0e3c45f 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
@@ -140,6 +140,9 @@
         return lldb::eLanguageTypeObjC;
     }
     
+    lldb::TypeCategoryImplSP
+    GetFormatters () override;
+    
     std::vector<ConstString>
     GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic) override;