Added support for finding and global variables in the SBTarget and SBModule
level in the public API. 

Also modified the ValueObject values to be able to display global variables
without having a valid running process. The globals will read themselves from
the object file section data if there is no process, and from the process if
there is one.

Also fixed an issue where modifications for dynamic types could cause child
values of ValueObjects to not show up if the value was unable to evaluate
itself (children of NULL pointer objects).



git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@134102 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/lldb/API/SBDefines.h b/include/lldb/API/SBDefines.h
index 9afd133..8f60371 100644
--- a/include/lldb/API/SBDefines.h
+++ b/include/lldb/API/SBDefines.h
@@ -57,6 +57,7 @@
 class SBTarget;
 class SBThread;
 class SBValue;
+class SBValueList;
 
 }
 
diff --git a/include/lldb/API/SBModule.h b/include/lldb/API/SBModule.h
index e0252f4..f90d78c 100644
--- a/include/lldb/API/SBModule.h
+++ b/include/lldb/API/SBModule.h
@@ -12,6 +12,7 @@
 
 #include "lldb/API/SBDefines.h"
 #include "lldb/API/SBSymbolContext.h"
+#include "lldb/API/SBValueList.h"
 
 namespace lldb {
 
@@ -80,6 +81,12 @@
                    bool append, 
                    lldb::SBSymbolContextList& sc_list);
 
+    lldb::SBValueList
+    FindGlobalVariables (lldb::SBTarget &target, 
+                         const char *name, 
+                         uint32_t max_matches);
+    
+
 private:
     friend class SBAddress;
     friend class SBFrame;
diff --git a/include/lldb/API/SBTarget.h b/include/lldb/API/SBTarget.h
index 94a720f..283ba57 100644
--- a/include/lldb/API/SBTarget.h
+++ b/include/lldb/API/SBTarget.h
@@ -189,6 +189,10 @@
                    bool append, 
                    lldb::SBSymbolContextList& sc_list);
 
+    lldb::SBValueList
+    FindGlobalVariables (const char *name, 
+                         uint32_t max_matches);
+
     void
     Clear ();
 
@@ -260,6 +264,7 @@
     friend class SBFunction;
     friend class SBProcess;
     friend class SBSymbol;
+    friend class SBModule;
 
     //------------------------------------------------------------------
     // Constructors are private, use static Target::Create function to
diff --git a/include/lldb/API/SBValueList.h b/include/lldb/API/SBValueList.h
index 6df9429..578f62e 100644
--- a/include/lldb/API/SBValueList.h
+++ b/include/lldb/API/SBValueList.h
@@ -30,6 +30,9 @@
     void
     Append (const lldb::SBValue &val_obj);
 
+    void
+    Append (const lldb::SBValueList& value_list);
+
     uint32_t
     GetSize() const;
 
@@ -58,7 +61,10 @@
     
     lldb_private::ValueObjectList *
     get ();
-    
+
+    lldb_private::ValueObjectList &
+    ref ();
+
 #endif
 
 private:
diff --git a/include/lldb/Core/ValueObject.h b/include/lldb/Core/ValueObject.h
index e033ec1..82ed45c 100644
--- a/include/lldb/Core/ValueObject.h
+++ b/include/lldb/Core/ValueObject.h
@@ -239,6 +239,9 @@
     
     virtual bool
     IsPossibleCPlusPlusDynamicType ();
+    
+    virtual bool
+    IsPossibleDynamicType ();
 
     virtual bool
     IsBaseClass ()
diff --git a/include/lldb/Core/ValueObjectList.h b/include/lldb/Core/ValueObjectList.h
index 9c5cde6..2429320 100644
--- a/include/lldb/Core/ValueObjectList.h
+++ b/include/lldb/Core/ValueObjectList.h
@@ -44,6 +44,9 @@
     void
     Append (const lldb::ValueObjectSP &val_obj_sp);
 
+    void
+    Append (const ValueObjectList &valobj_list);
+
     lldb::ValueObjectSP
     FindValueObjectByPointer (ValueObject *valobj);
 
diff --git a/include/lldb/Symbol/ClangASTContext.h b/include/lldb/Symbol/ClangASTContext.h
index 73c9954..00f27d2 100644
--- a/include/lldb/Symbol/ClangASTContext.h
+++ b/include/lldb/Symbol/ClangASTContext.h
@@ -635,6 +635,11 @@
                                     lldb::clang_type_t *target_type = NULL);
 
     static bool
+    IsPossibleDynamicType (clang::ASTContext *ast, 
+                           lldb::clang_type_t clang_type, 
+                           lldb::clang_type_t *dynamic_pointee_type = NULL);
+
+    static bool
     IsCStringType (lldb::clang_type_t clang_type, uint32_t &length);
 
     static bool
diff --git a/source/API/SBModule.cpp b/source/API/SBModule.cpp
index 0c4eba4..53172f3 100644
--- a/source/API/SBModule.cpp
+++ b/source/API/SBModule.cpp
@@ -15,6 +15,10 @@
 #include "lldb/Core/Module.h"
 #include "lldb/Core/Log.h"
 #include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/Target.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -307,3 +311,34 @@
     return 0;
 }
 
+
+SBValueList
+SBModule::FindGlobalVariables (SBTarget &target, const char *name, uint32_t max_matches)
+{
+    SBValueList sb_value_list;
+    if (m_opaque_sp)
+    {
+        VariableList variable_list;
+        const uint32_t match_count = m_opaque_sp->FindGlobalVariables (ConstString (name), 
+                                                                       false, 
+                                                                       max_matches,
+                                                                       variable_list);
+
+        if (match_count > 0)
+        {
+            ValueObjectList &value_object_list = sb_value_list.ref();
+            for (uint32_t i=0; i<match_count; ++i)
+            {
+                lldb::ValueObjectSP valobj_sp;
+                if (target.IsValid())
+                    valobj_sp = ValueObjectVariable::Create (target.get(), variable_list.GetVariableAtIndex(i));
+                else
+                    valobj_sp = ValueObjectVariable::Create (NULL, variable_list.GetVariableAtIndex(i));
+                if (valobj_sp)
+                    value_object_list.Append(valobj_sp);
+            }
+        }
+    }
+    
+    return sb_value_list;
+}
diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp
index 7098604..6a17bb4 100644
--- a/source/API/SBTarget.cpp
+++ b/source/API/SBTarget.cpp
@@ -11,8 +11,12 @@
 
 #include "lldb/lldb-public.h"
 
+#include "lldb/API/SBDebugger.h"
+#include "lldb/API/SBBreakpoint.h"
 #include "lldb/API/SBFileSpec.h"
+#include "lldb/API/SBListener.h"
 #include "lldb/API/SBModule.h"
+#include "lldb/API/SBProcess.h"
 #include "lldb/API/SBStream.h"
 #include "lldb/API/SBSymbolContextList.h"
 #include "lldb/Breakpoint/BreakpointID.h"
@@ -22,16 +26,19 @@
 #include "lldb/Core/Address.h"
 #include "lldb/Core/AddressResolver.h"
 #include "lldb/Core/AddressResolverName.h"
-#include "lldb/Interpreter/Args.h"
 #include "lldb/Core/ArchSpec.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Disassembler.h"
-#include "lldb/Host/FileSpec.h"
 #include "lldb/Core/Log.h"
 #include "lldb/Core/RegularExpression.h"
 #include "lldb/Core/SearchFilter.h"
 #include "lldb/Core/STLUtils.h"
+#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/Host/FileSpec.h"
 #include "lldb/Host/Host.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Symbol/VariableList.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Target/TargetList.h"
@@ -39,10 +46,6 @@
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "../source/Commands/CommandObjectBreakpoint.h"
 
-#include "lldb/API/SBDebugger.h"
-#include "lldb/API/SBProcess.h"
-#include "lldb/API/SBListener.h"
-#include "lldb/API/SBBreakpoint.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -872,3 +875,35 @@
     return 0;
 }
 
+SBValueList
+SBTarget::FindGlobalVariables (const char *name, uint32_t max_matches)
+{
+    SBValueList sb_value_list;
+    
+    if (m_opaque_sp)
+    {
+        VariableList variable_list;
+        const bool append = true;
+        const uint32_t match_count = m_opaque_sp->GetImages().FindGlobalVariables (ConstString (name), 
+                                                                                   append, 
+                                                                                   max_matches,
+                                                                                   variable_list);
+        
+        if (match_count > 0)
+        {
+            ExecutionContextScope *exe_scope = m_opaque_sp->GetProcessSP().get();
+            if (exe_scope == NULL)
+                exe_scope = m_opaque_sp.get();
+            ValueObjectList &value_object_list = sb_value_list.ref();
+            for (uint32_t i=0; i<match_count; ++i)
+            {
+                lldb::ValueObjectSP valobj_sp (ValueObjectVariable::Create (exe_scope, variable_list.GetVariableAtIndex(i)));
+                if (valobj_sp)
+                    value_object_list.Append(valobj_sp);
+            }
+        }
+    }
+
+    return sb_value_list;
+}
+
diff --git a/source/API/SBValueList.cpp b/source/API/SBValueList.cpp
index bcddedf..4e0fea5 100644
--- a/source/API/SBValueList.cpp
+++ b/source/API/SBValueList.cpp
@@ -25,10 +25,10 @@
 SBValueList::SBValueList (const SBValueList &rhs) :
     m_opaque_ap ()
 {
-    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
 
     if (rhs.IsValid())
-        m_opaque_ap.reset (new lldb_private::ValueObjectList (*rhs));
+        m_opaque_ap.reset (new ValueObjectList (*rhs));
 
     if (log)
     {
@@ -38,13 +38,13 @@
     }
 }
 
-SBValueList::SBValueList (const lldb_private::ValueObjectList *lldb_object_ptr) :
+SBValueList::SBValueList (const ValueObjectList *lldb_object_ptr) :
     m_opaque_ap ()
 {
-    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
 
     if (lldb_object_ptr)
-        m_opaque_ap.reset (new lldb_private::ValueObjectList (*lldb_object_ptr));
+        m_opaque_ap.reset (new ValueObjectList (*lldb_object_ptr));
 
     if (log)
     {
@@ -70,32 +70,32 @@
     if (this != &rhs)
     {
         if (rhs.IsValid())
-            m_opaque_ap.reset (new lldb_private::ValueObjectList (*rhs));
+            m_opaque_ap.reset (new ValueObjectList (*rhs));
         else
             m_opaque_ap.reset ();
     }
     return *this;
 }
 
-lldb_private::ValueObjectList *
+ValueObjectList *
 SBValueList::operator->()
 {
     return m_opaque_ap.get();
 }
 
-lldb_private::ValueObjectList &
+ValueObjectList &
 SBValueList::operator*()
 {
     return *m_opaque_ap;
 }
 
-const lldb_private::ValueObjectList *
+const ValueObjectList *
 SBValueList::operator->() const
 {
     return m_opaque_ap.get();
 }
 
-const lldb_private::ValueObjectList &
+const ValueObjectList &
 SBValueList::operator*() const
 {
     return *m_opaque_ap;
@@ -121,11 +121,21 @@
     }
 }
 
+void
+SBValueList::Append (const lldb::SBValueList& value_list)
+{
+    if (value_list.IsValid())
+    {
+        CreateIfNeeded ();
+        m_opaque_ap->Append (*value_list);
+    }
+}
+
 
 SBValue
 SBValueList::GetValueAtIndex (uint32_t idx) const
 {
-    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
 
     //if (log)
     //    log->Printf ("SBValueList::GetValueAtIndex (uint32_t idx) idx = %d", idx);
@@ -148,7 +158,7 @@
 uint32_t
 SBValueList::GetSize () const
 {
-    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
 
     //if (log)
     //    log->Printf ("SBValueList::GetSize ()");
@@ -180,9 +190,17 @@
     return sb_value;
 }
 
-lldb_private::ValueObjectList *
+ValueObjectList *
 SBValueList::get ()
 {
     return m_opaque_ap.get();
 }
 
+ValueObjectList &
+SBValueList::ref ()
+{
+    CreateIfNeeded();
+    return *m_opaque_ap.get();
+}
+
+
diff --git a/source/Core/Value.cpp b/source/Core/Value.cpp
index 2d8ac91..2ba490e 100644
--- a/source/Core/Value.cpp
+++ b/source/Core/Value.cpp
@@ -516,6 +516,7 @@
     Error error;
     lldb::addr_t address = LLDB_INVALID_ADDRESS;
     AddressType address_type = eAddressTypeFile;
+    Address file_so_addr;
     switch (m_value_type)
     {
     default:
@@ -541,11 +542,11 @@
     case eValueTypeLoadAddress:
         if (exe_ctx == NULL)
         {
-            error.SetErrorString ("can't read memory (no execution context)");
+            error.SetErrorString ("can't read load address (no execution context)");
         }
         else if (exe_ctx->process == NULL)
         {
-            error.SetErrorString ("can't read memory (invalid process)");
+            error.SetErrorString ("can't read load address (invalid process)");
         }
         else
         {
@@ -557,6 +558,15 @@
         break;
 
     case eValueTypeFileAddress:
+        if (exe_ctx == NULL)
+        {
+            error.SetErrorString ("can't read file address (no execution context)");
+        }
+        else if (exe_ctx->target == NULL)
+        {
+            error.SetErrorString ("can't read file address (invalid target)");
+        }
+        else
         {
             // The only thing we can currently lock down to a module so that
             // we can resolve a file address, is a variable.
@@ -564,9 +574,10 @@
 
             if (GetVariable())
             {
-                lldb::addr_t file_addr = m_value.ULongLong(LLDB_INVALID_ADDRESS);
-                if (file_addr != LLDB_INVALID_ADDRESS)
+                address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
+                if (address != LLDB_INVALID_ADDRESS)
                 {
+                    bool resolved = false;
                     SymbolContext var_sc;
                     variable->CalculateSymbolContext(&var_sc);
                     if (var_sc.module_sp)
@@ -574,31 +585,46 @@
                         ObjectFile *objfile = var_sc.module_sp->GetObjectFile();
                         if (objfile)
                         {
-                            Address so_addr(file_addr, objfile->GetSectionList());
-                            address = so_addr.GetLoadAddress (exe_ctx->target);
-                            if (address != LLDB_INVALID_ADDRESS)
+                            Address so_addr(address, objfile->GetSectionList());
+                            addr_t load_address = so_addr.GetLoadAddress (exe_ctx->target);
+                            if (load_address != LLDB_INVALID_ADDRESS)
                             {
+                                resolved = true;
+                                address = load_address;
                                 address_type = eAddressTypeLoad;
                                 data.SetByteOrder(exe_ctx->target->GetArchitecture().GetByteOrder());
                                 data.SetAddressByteSize(exe_ctx->target->GetArchitecture().GetAddressByteSize());
                             }
                             else
                             {
-                                data.SetByteOrder(objfile->GetByteOrder());
-                                data.SetAddressByteSize(objfile->GetAddressByteSize());
+                                if (so_addr.IsSectionOffset())
+                                {
+                                    resolved = true;
+                                    file_so_addr = so_addr;
+                                    data.SetByteOrder(objfile->GetByteOrder());
+                                    data.SetAddressByteSize(objfile->GetAddressByteSize());
+                                }
                             }
                         }
-                        if (address_type == eAddressTypeFile)
-                            error.SetErrorStringWithFormat ("%s is not loaded.\n", var_sc.module_sp->GetFileSpec().GetFilename().AsCString());
                     }
-                    else
+                    if (!resolved)
                     {
-                        error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s'", file_addr, variable->GetName().AsCString(""));
+                        if (var_sc.module_sp)
+                            error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s' in %s%s%s", 
+                                                            address, 
+                                                            variable->GetName().AsCString(""),
+                                                            var_sc.module_sp->GetFileSpec().GetDirectory().GetCString(),
+                                                            var_sc.module_sp->GetFileSpec().GetDirectory() ? "/" : "",
+                                                            var_sc.module_sp->GetFileSpec().GetFilename().GetCString());
+                        else
+                            error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s'", 
+                                                            address, 
+                                                            variable->GetName().AsCString(""));
                     }
                 }
                 else
                 {
-                    error.SetErrorString ("Invalid file address.");
+                    error.SetErrorString ("invalid file address");
                 }
             }
             else
@@ -651,14 +677,28 @@
             // The address is an address in this process, so just copy it
             memcpy (dst, (uint8_t*)NULL + address, byte_size);
         }
-        else if (address_type == eAddressTypeLoad)
+        else if ((address_type == eAddressTypeLoad) || (address_type == eAddressTypeFile))
         {
-            if (exe_ctx->process->ReadMemory(address, dst, byte_size, error) != byte_size)
+            if (file_so_addr.IsValid())
             {
-                if (error.Success())
-                    error.SetErrorStringWithFormat("read %u bytes of memory from 0x%llx failed", (uint64_t)address, byte_size);
-                else
+                // We have a file address that we were able to translate into a
+                // section offset address so we might be able to read this from
+                // the object files if we don't have a live process. Lets always
+                // try and read from the process if we have one though since we
+                // want to read the actual value by setting "prefer_file_cache"
+                // to false. 
+                const bool prefer_file_cache = false;
+                if (exe_ctx->target->ReadMemory(file_so_addr, prefer_file_cache, dst, byte_size, error) != byte_size)
+                {
                     error.SetErrorStringWithFormat("read memory from 0x%llx failed", (uint64_t)address);
+                }
+            }
+            else
+            {
+                if (exe_ctx->process->ReadMemory(address, dst, byte_size, error) != byte_size)
+                {
+                    error.SetErrorStringWithFormat("read memory from 0x%llx failed", (uint64_t)address);
+                }
             }
         }
         else
diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp
index 6471972..c4bfc3c 100644
--- a/source/Core/ValueObject.cpp
+++ b/source/Core/ValueObject.cpp
@@ -285,21 +285,21 @@
 ValueObject::GetChildAtIndex (uint32_t idx, bool can_create)
 {
     ValueObjectSP child_sp;
-    if (UpdateValueIfNeeded())
+    // We may need to update our value if we are dynamic
+    if (IsPossibleDynamicType ())
+        UpdateValueIfNeeded();
+    if (idx < GetNumChildren())
     {
-        if (idx < GetNumChildren())
+        // Check if we have already made the child value object?
+        if (can_create && m_children[idx] == NULL)
         {
-            // Check if we have already made the child value object?
-            if (can_create && m_children[idx] == NULL)
-            {
-                // No we haven't created the child at this index, so lets have our
-                // subclass do it and cache the result for quick future access.
-                m_children[idx] = CreateChildAtIndex (idx, false, 0);
-            }
-            
-            if (m_children[idx] != NULL)
-                return m_children[idx]->GetSP();
+            // No we haven't created the child at this index, so lets have our
+            // subclass do it and cache the result for quick future access.
+            m_children[idx] = CreateChildAtIndex (idx, false, 0);
         }
+        
+        if (m_children[idx] != NULL)
+            return m_children[idx]->GetSP();
     }
     return child_sp;
 }
@@ -322,36 +322,37 @@
     // need a vector of indexes that can get us down to the correct child
     ValueObjectSP child_sp;
 
-    if (UpdateValueIfNeeded())
+    // We may need to update our value if we are dynamic
+    if (IsPossibleDynamicType ())
+        UpdateValueIfNeeded();
+
+    std::vector<uint32_t> child_indexes;
+    clang::ASTContext *clang_ast = GetClangAST();
+    void *clang_type = GetClangType();
+    bool omit_empty_base_classes = true;
+    const size_t num_child_indexes =  ClangASTContext::GetIndexOfChildMemberWithName (clang_ast,
+                                                                                      clang_type,
+                                                                                      name.GetCString(),
+                                                                                      omit_empty_base_classes,
+                                                                                      child_indexes);
+    if (num_child_indexes > 0)
     {
-        std::vector<uint32_t> child_indexes;
-        clang::ASTContext *clang_ast = GetClangAST();
-        void *clang_type = GetClangType();
-        bool omit_empty_base_classes = true;
-        const size_t num_child_indexes =  ClangASTContext::GetIndexOfChildMemberWithName (clang_ast,
-                                                                                          clang_type,
-                                                                                          name.GetCString(),
-                                                                                          omit_empty_base_classes,
-                                                                                          child_indexes);
-        if (num_child_indexes > 0)
+        std::vector<uint32_t>::const_iterator pos = child_indexes.begin ();
+        std::vector<uint32_t>::const_iterator end = child_indexes.end ();
+
+        child_sp = GetChildAtIndex(*pos, can_create);
+        for (++pos; pos != end; ++pos)
         {
-            std::vector<uint32_t>::const_iterator pos = child_indexes.begin ();
-            std::vector<uint32_t>::const_iterator end = child_indexes.end ();
-
-            child_sp = GetChildAtIndex(*pos, can_create);
-            for (++pos; pos != end; ++pos)
+            if (child_sp)
             {
-                if (child_sp)
-                {
-                    ValueObjectSP new_child_sp(child_sp->GetChildAtIndex (*pos, can_create));
-                    child_sp = new_child_sp;
-                }
-                else
-                {
-                    child_sp.reset();
-                }
-
+                ValueObjectSP new_child_sp(child_sp->GetChildAtIndex (*pos, can_create));
+                child_sp = new_child_sp;
             }
+            else
+            {
+                child_sp.reset();
+            }
+
         }
     }
     return child_sp;
@@ -391,62 +392,59 @@
 {
     ValueObject *valobj = NULL;
     
-    if (UpdateValueIfNeeded())
+    bool omit_empty_base_classes = true;
+
+    std::string child_name_str;
+    uint32_t child_byte_size = 0;
+    int32_t child_byte_offset = 0;
+    uint32_t child_bitfield_bit_size = 0;
+    uint32_t child_bitfield_bit_offset = 0;
+    bool child_is_base_class = false;
+    bool child_is_deref_of_parent = false;
+
+    const bool transparent_pointers = synthetic_array_member == false;
+    clang::ASTContext *clang_ast = GetClangAST();
+    clang_type_t clang_type = GetClangType();
+    clang_type_t child_clang_type;
+    
+    ExecutionContext exe_ctx;
+    GetExecutionContextScope()->CalculateExecutionContext (exe_ctx);
+    
+    child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (&exe_ctx,
+                                                                  clang_ast,
+                                                                  GetName().GetCString(),
+                                                                  clang_type,
+                                                                  idx,
+                                                                  transparent_pointers,
+                                                                  omit_empty_base_classes,
+                                                                  child_name_str,
+                                                                  child_byte_size,
+                                                                  child_byte_offset,
+                                                                  child_bitfield_bit_size,
+                                                                  child_bitfield_bit_offset,
+                                                                  child_is_base_class,
+                                                                  child_is_deref_of_parent);
+    if (child_clang_type && child_byte_size)
     {
-        bool omit_empty_base_classes = true;
+        if (synthetic_index)
+            child_byte_offset += child_byte_size * synthetic_index;
 
-        std::string child_name_str;
-        uint32_t child_byte_size = 0;
-        int32_t child_byte_offset = 0;
-        uint32_t child_bitfield_bit_size = 0;
-        uint32_t child_bitfield_bit_offset = 0;
-        bool child_is_base_class = false;
-        bool child_is_deref_of_parent = false;
+        ConstString child_name;
+        if (!child_name_str.empty())
+            child_name.SetCString (child_name_str.c_str());
 
-        const bool transparent_pointers = synthetic_array_member == false;
-        clang::ASTContext *clang_ast = GetClangAST();
-        clang_type_t clang_type = GetClangType();
-        clang_type_t child_clang_type;
-        
-        ExecutionContext exe_ctx;
-        GetExecutionContextScope()->CalculateExecutionContext (exe_ctx);
-        
-        child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (&exe_ctx,
-                                                                      clang_ast,
-                                                                      GetName().GetCString(),
-                                                                      clang_type,
-                                                                      idx,
-                                                                      transparent_pointers,
-                                                                      omit_empty_base_classes,
-                                                                      child_name_str,
-                                                                      child_byte_size,
-                                                                      child_byte_offset,
-                                                                      child_bitfield_bit_size,
-                                                                      child_bitfield_bit_offset,
-                                                                      child_is_base_class,
-                                                                      child_is_deref_of_parent);
-        if (child_clang_type && child_byte_size)
-        {
-            if (synthetic_index)
-                child_byte_offset += child_byte_size * synthetic_index;
-
-            ConstString child_name;
-            if (!child_name_str.empty())
-                child_name.SetCString (child_name_str.c_str());
-
-            valobj = new ValueObjectChild (*this,
-                                           clang_ast,
-                                           child_clang_type,
-                                           child_name,
-                                           child_byte_size,
-                                           child_byte_offset,
-                                           child_bitfield_bit_size,
-                                           child_bitfield_bit_offset,
-                                           child_is_base_class,
-                                           child_is_deref_of_parent);            
-            if (m_pointers_point_to_load_addrs)
-                valobj->SetPointersPointToLoadAddrs (m_pointers_point_to_load_addrs);
-        }
+        valobj = new ValueObjectChild (*this,
+                                       clang_ast,
+                                       child_clang_type,
+                                       child_name,
+                                       child_byte_size,
+                                       child_byte_offset,
+                                       child_bitfield_bit_size,
+                                       child_bitfield_bit_offset,
+                                       child_is_base_class,
+                                       child_is_deref_of_parent);            
+        if (m_pointers_point_to_load_addrs)
+            valobj->SetPointersPointToLoadAddrs (m_pointers_point_to_load_addrs);
     }
     
     return valobj;
@@ -994,6 +992,12 @@
     return ClangASTContext::IsPossibleCPlusPlusDynamicType (GetClangAST (), GetClangType());
 }
 
+bool
+ValueObject::IsPossibleDynamicType ()
+{
+    return ClangASTContext::IsPossibleDynamicType (GetClangAST (), GetClangType());
+}
+
 ValueObjectSP
 ValueObject::GetSyntheticArrayMemberFromPointer (int32_t index, bool can_create)
 {
diff --git a/source/Core/ValueObjectList.cpp b/source/Core/ValueObjectList.cpp
index 8913d4d..f732a69 100644
--- a/source/Core/ValueObjectList.cpp
+++ b/source/Core/ValueObjectList.cpp
@@ -51,6 +51,16 @@
     m_value_objects.push_back(val_obj_sp);
 }
 
+void
+ValueObjectList::Append (const ValueObjectList &valobj_list)
+{
+    std::copy(valobj_list.m_value_objects.begin(),  // source begin
+              valobj_list.m_value_objects.end(),    // source end
+              back_inserter(m_value_objects));      // destination
+    
+}
+
+
 uint32_t
 ValueObjectList::GetSize() const
 {
diff --git a/source/Core/ValueObjectVariable.cpp b/source/Core/ValueObjectVariable.cpp
index e2a281b..79692a0 100644
--- a/source/Core/ValueObjectVariable.cpp
+++ b/source/Core/ValueObjectVariable.cpp
@@ -169,7 +169,7 @@
                 // Make sure this type has a value before we try and read it
 
                 // If we have a file address, convert it to a load address if we can.
-                if (value_type == Value::eValueTypeFileAddress && exe_ctx.process)
+                if (value_type == Value::eValueTypeFileAddress && exe_ctx.process && exe_ctx.process->IsAlive())
                 {
                     lldb::addr_t file_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
                     if (file_addr != LLDB_INVALID_ADDRESS)
diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp
index b692ae5..fb55a51 100644
--- a/source/Symbol/ClangASTContext.cpp
+++ b/source/Symbol/ClangASTContext.cpp
@@ -4046,6 +4046,150 @@
 }
 
 bool
+ClangASTContext::IsPossibleDynamicType (clang::ASTContext *ast, clang_type_t clang_type, clang_type_t *dynamic_pointee_type)
+{
+    QualType pointee_qual_type;
+    if (clang_type)
+    {
+        QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+        const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+        bool success = false;
+        switch (type_class)
+        {
+            case clang::Type::Builtin:
+                if (cast<clang::BuiltinType>(qual_type)->getKind() == clang::BuiltinType::ObjCId)
+                {
+                    if (dynamic_pointee_type)
+                        *dynamic_pointee_type = clang_type;
+                    return true;
+                }
+                break;
+
+            case clang::Type::ObjCObjectPointer:
+                if (dynamic_pointee_type)
+                    *dynamic_pointee_type = cast<ObjCObjectPointerType>(qual_type)->getPointeeType().getAsOpaquePtr();
+                return true;
+
+            case clang::Type::Pointer:
+                pointee_qual_type = cast<PointerType>(qual_type)->getPointeeType();
+                success = true;
+                break;
+                
+            case clang::Type::LValueReference:
+            case clang::Type::RValueReference:
+                pointee_qual_type = cast<ReferenceType>(qual_type)->getPointeeType();
+                success = true;
+                break;
+                
+            case clang::Type::Typedef:
+                return ClangASTContext::IsPossibleCPlusPlusDynamicType (ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), dynamic_pointee_type);
+                
+            default:
+                break;
+        }
+        
+        if (success)
+        {
+            // Check to make sure what we are pointing too is a possible dynamic C++ type
+            // We currently accept any "void *" (in case we have a class that has been
+            // watered down to an opaque pointer) and virtual C++ classes.
+            const clang::Type::TypeClass pointee_type_class = pointee_qual_type->getTypeClass();
+            switch (pointee_type_class)
+            {
+                case clang::Type::Builtin:
+                    switch (cast<clang::BuiltinType>(pointee_qual_type)->getKind())
+                    {
+                        case clang::BuiltinType::UnknownAny:
+                        case clang::BuiltinType::Void:
+                            if (dynamic_pointee_type)
+                                *dynamic_pointee_type = pointee_qual_type.getAsOpaquePtr();
+                            return true;
+                            
+                        case clang::BuiltinType::NullPtr:  
+                        case clang::BuiltinType::Bool:
+                        case clang::BuiltinType::Char_U:
+                        case clang::BuiltinType::UChar:
+                        case clang::BuiltinType::WChar_U:
+                        case clang::BuiltinType::Char16:
+                        case clang::BuiltinType::Char32:
+                        case clang::BuiltinType::UShort:
+                        case clang::BuiltinType::UInt:
+                        case clang::BuiltinType::ULong:
+                        case clang::BuiltinType::ULongLong:
+                        case clang::BuiltinType::UInt128:
+                        case clang::BuiltinType::Char_S:
+                        case clang::BuiltinType::SChar:
+                        case clang::BuiltinType::WChar_S:
+                        case clang::BuiltinType::Short:
+                        case clang::BuiltinType::Int:
+                        case clang::BuiltinType::Long:
+                        case clang::BuiltinType::LongLong:
+                        case clang::BuiltinType::Int128:
+                        case clang::BuiltinType::Float:
+                        case clang::BuiltinType::Double:
+                        case clang::BuiltinType::LongDouble:
+                        case clang::BuiltinType::Dependent:
+                        case clang::BuiltinType::Overload:
+                        case clang::BuiltinType::ObjCId:
+                        case clang::BuiltinType::ObjCClass:
+                        case clang::BuiltinType::ObjCSel:
+                        case clang::BuiltinType::BoundMember:
+                            break;
+                    }
+                    break;
+
+                case clang::Type::Record:
+                    {
+                        CXXRecordDecl *cxx_record_decl = pointee_qual_type->getAsCXXRecordDecl();
+                        if (cxx_record_decl)
+                        {
+                            if (GetCompleteQualType (ast, pointee_qual_type))
+                            {
+                                success = cxx_record_decl->isDynamicClass();
+                            }
+                            else
+                            {
+                                // We failed to get the complete type, so we have to 
+                                // treat this as a void * which we might possibly be
+                                // able to complete
+                                success = true;
+                            }
+                            if (success)
+                            {
+                                if (dynamic_pointee_type)
+                                    *dynamic_pointee_type = pointee_qual_type.getAsOpaquePtr();
+                                return true;
+                            }
+                        }
+                    }
+                    break;
+                    
+                case clang::Type::ObjCObject:
+                case clang::Type::ObjCInterface:
+                    {
+                        const clang::ObjCObjectType *objc_class_type = pointee_qual_type->getAsObjCQualifiedInterfaceType();
+                        if (objc_class_type)
+                        {
+                            GetCompleteQualType (ast, pointee_qual_type);
+                            if (dynamic_pointee_type)
+                                *dynamic_pointee_type = pointee_qual_type.getAsOpaquePtr();
+                            return true;
+                        }
+                    }
+                    break;
+
+                default:
+                    break;
+            }
+        }
+    }
+    if (dynamic_pointee_type)
+        *dynamic_pointee_type = NULL;
+    return false;
+}
+
+
+bool
 ClangASTContext::IsPossibleCPlusPlusDynamicType (clang::ASTContext *ast, clang_type_t clang_type, clang_type_t *dynamic_pointee_type)
 {
     QualType pointee_qual_type;